

  /////////////////////////////////////////////////////////////////
  ////                                                         ////
  ////    FUNCTIONS RELATED TO TABLE CREATION AND BEHAVIOUR    ////
  ////                                                         ////
  /////////////////////////////////////////////////////////////////


      // OBJECT CLASS FOR CREATING DYNAMIC TABLES ...
        function dynTable(mainData, parentObj, proxy) {
        // gather scope
          var classRoot       = this;
          classRoot.proxy     = window[proxy];
          classRoot.mainData  = mainData;
        //////////////////////////////////////////////////
        ////  INITIALIZES A NEW TABLE                 ////
        //////////////////////////////////////////////////
          classRoot.initTable = function(tableData) {
            if(tableData && typeof(tableData) == 'string') {
              if (tableData.indexOf("I'm") != -1) { tableData = tableData.split("I'm").join('I am'); }
              tableData = eval(tableData);
            }
            if (tableData && classRoot.proxy)  { classRoot.proxy(tableData); }
            if (tableData && typeof(tableData[0]) != 'undefined' && typeof(tableData[0]) == 'boolean') { tableData = tableData[1]; }
            if (!tableData) {
            // set some properties
              classRoot.proxy     = window[proxy];
              classRoot.mainData  = mainData;
              classRoot.baseReq   = mainData[4];
              classRoot.sortCol   = mainData[3][0];
              classRoot.lastSort  = false;
              classRoot.sortDir   = 'fwd';
              classRoot.filters   = [];
              classRoot.lastInfo  = false;
              classRoot.infoIdStr = false;
              classRoot.showInf   = false;
              classRoot.menuTimer = false;
              classRoot.rowProp   = (client.engine != 'msie') ? 'table-row' : 'block';
            // change from [boolean] to [name, bool/value, comparison]
              //for (var loop=1; loop<mainData[3].length; loop++) { classRoot.filters.push(false); }
              for (var loop=1; loop<mainData[3].length; loop++) {
                var filtArr = mainData[3][loop];
                try { classRoot.filters.push([filtArr[0][0], false, false]); } catch (e) {}
              }
            // start by creating filters
              if (classRoot.filters.length > 0) { classRoot.setFilts(parentObj); }
            // create table element
              classRoot.table = document.createElement('table');
              classRoot.table.className = 'dynTable';
              classRoot.table = parentObj.appendChild(classRoot.table);
              classRoot.table = classRoot.table.appendChild(document.createElement('tbody')); // yet another irritating IE workaround
            // set up table header row
              classRoot.addRow(mainData[0], classRoot.table);
            // request content data from server
            // last minute change ... could be better
              var clickFilt = function(thisName, thisValue) {
               // simulate click
                var allFilts  = classRoot.filtParent.childNodes;
                for (var loop = 0; loop < allFilts.length; loop++) {
                  var thisFilt = allFilts[loop];
                  if (thisFilt.getAttribute('optcolumn') == thisName) {
                    var theseOpts = thisFilt.lastChild.childNodes;
                    for (var loop2 = 0; loop2 < theseOpts.length; loop2++) {
                      var thisOpt = theseOpts[loop2];
                      var optiValue = thisOpt.getAttribute('optvalue');
                      if (optiValue == thisValue) { thisOpt.onclick(); }
                    }
                  }
                }
                handleLinkage();
              }
            // read from page querystring, allow deeplinking to filters and row sortage
              var initialRequest = classRoot.baseReq;

              if (classRoot.filters.length && qrystr.fn0 && qrystr.fv0 && qrystr.fc0) {
                initialRequest += (initialRequest.indexOf('?') == -1) ? '?' : '&';
                initialRequest += 'fn0='+ qrystr.fn0 +'&fv0=' + qrystr.fv0 + '&fc0=' + qrystr.fc0;
                clickFilt(qrystr.fn0, qrystr.fv0);
                if (qrystr.fn1 && qrystr.fv1 && qrystr.fc1) {
                  initialRequest += '&fn1='+ qrystr.fn1 +'&fv1=' + qrystr.fv1 + '&fc1=' + qrystr.fc1;
                  clickFilt(qrystr.fn1, qrystr.fv1)
                  if (qrystr.fn2 && qrystr.fv2 && qrystr.fc2) {
                    initialRequest += '&fn2='+ qrystr.fn1 +'&fv2=' + qrystr.fv2 + '&fc2=' + qrystr.fc1;
                    clickFilt(qrystr.fn2, qrystr.fv2)
                  }
                }
              }

              if (classRoot.sortCol) {
                initialRequest += (initialRequest.indexOf('?') == -1) ? '?' : '&';
                initialRequest += 'sort=' + classRoot.sortCol;
              }
              ajax.get(initialRequest, classRoot.initTable);
            } else {
            // store content data from server
              classRoot.contData = tableData;
            // fill table up initially.
              classRoot.fillTable(false);
            }
          }
        //////////////////////////////////////////////////
        ////  REFRESHES CONTENT DATA AND REPOPULATES  ////
        //////////////////////////////////////////////////
          classRoot.updateContent = function() {
          // start querystring
            var qryString = '&';
          // add any filters applied.
            if (classRoot.filters.length) {
              for (var thisFilter in classRoot.filters) {
                if (classRoot.filters[thisFilter][1]) {
                  qryString += 'fn' + thisFilter + '=' +  escape(classRoot.filters[thisFilter][0]) + '&';
                  qryString += 'fv' + thisFilter + '=' +  escape(classRoot.filters[thisFilter][1]) + '&';
                  qryString += 'fc' + thisFilter + '=' +  escape(classRoot.filters[thisFilter][2]) + '&';
                }
              }
            }
          // add sort index
            qryString += 'sort=' + classRoot.sortCol;
          // get new data and fill table with it
            ajax.get(classRoot.baseReq + qryString, classRoot.fillTable);
          }
        //////////////////////////////////////////////////
        ////  CREATES FILTERS FOR TABLE               ////
        //////////////////////////////////////////////////
        // this could probably use some cleanup ...
          classRoot.setFilts = function(parentObj) {
            var leftMargin = 0;
            if (classRoot.filters.length) {
                classRoot.filtParent = document.createElement('div');
                classRoot.filtParent = parentObj.appendChild(classRoot.filtParent);
                classRoot.filtParent.className = 'filterParent';
            }
            for (var thisFilt in classRoot.filters) {
              var optionsArr = classRoot.mainData[3][parseInt(thisFilt)+1][1];
                optionsArr.unshift(classRoot.mainData[3][parseInt(thisFilt)+1][0][1]);
                optionsArr.push(classRoot.mainData[3][parseInt(thisFilt)+1][0][2]);
              var select             = document.createElement('div');
                select.className   = 'dynTable';
                select.setAttribute('filterIndex', thisFilt);
                select.setAttribute('optColumn', classRoot.mainData[3][parseInt(thisFilt)+1][0][0]);
                select.onclick     = function() {
                  this.childNodes[2].className = (this.childNodes[2].className == '') ? 'open' : '';
                  if (this.firstChild.optValue != false) { this.firstChild.innerHTML = (this.childNodes[2].className == 'open') ? this.firstChild.defaultValue : this.firstChild.optName; }
                }
                select.onmouseout  = function() {
                  var thisObj    = this;
                  var killMenu   = function() {
                    thisObj.childNodes[2].className = '';
                    if (thisObj.firstChild.optValue != false) {
                      thisObj.firstChild.innerHTML = thisObj.firstChild.optName;
                    }
                  }
                  classRoot.menuTimer = setTimeout(killMenu, 10);
                }
                select.onmouseover = function() { if (classRoot.menuTimer) { clearTimeout(classRoot.menuTimer); classRoot.menuTimer = false; } }
              var label              = document.createElement('span');
              var label              = select.appendChild(label);
                label.setAttribute('optColumn', label.parentNode.getAttribute('optColumn'));
                label.innerHTML    = optionsArr[0];
                label.defaultValue = optionsArr[0];
                label.optValue     = false;
                label.optName      = optionsArr[0];
              var button             = document.createElement('img');
              var button             = select.appendChild(button);
                button.src         = '/global/assets/images/dyntable/dynTable-selectBtn.gif';
              var list               = document.createElement('ul');
              var list               = select.appendChild(list);
              for (var thisOpt in optionsArr) {
                if (thisOpt == 0) { continue; }
                var option = document.createElement('li');
                var option = list.appendChild(option);
                  option.innerHTML   = (typeof(optionsArr[thisOpt]) == 'string') ? optionsArr[thisOpt] : optionsArr[thisOpt][0];
                  option.setAttribute('optName',    (typeof(optionsArr[thisOpt]) == 'string') ? false : optionsArr[thisOpt][0]);//option.optName     = (typeof(optionsArr[thisOpt]) == 'string') ? false               : optionsArr[thisOpt][0];
                  option.setAttribute('optValue',   (typeof(optionsArr[thisOpt]) == 'string') ? false : optionsArr[thisOpt][1]);//option.optValue    = (typeof(optionsArr[thisOpt]) == 'string') ? false               : optionsArr[thisOpt][1];
                  option.setAttribute('optCompare', (typeof(optionsArr[thisOpt]) == 'string') ? false : optionsArr[thisOpt][2]);//option.optCompare  = (typeof(optionsArr[thisOpt]) == 'string') ? false               : optionsArr[thisOpt][2];
                  option.setAttribute('optColumn',  (typeof(optionsArr[thisOpt]) == 'string') ? false : optionsArr[0]);//new
                  option.className   = (thisOpt == (optionsArr.length-1)) ? 'killFilt' : '';
                  option.onmouseover = function() { if (this.className == '' ) { this.style.background = (this.className == 'current') ? '' : 'url(/global/assets/images/dyntable/dynTable-selectBg_o.gif)'; } }
                  option.onmouseout  = function() { this.style.backgroundImage = ''; }
                  option.setAttribute('optColumn', option.parentNode.parentNode.getAttribute('optColumn'));
                  option.onclick     = function() {
                  // set filter display
                    this.parentNode.parentNode.firstChild.innerHTML = (this.className == 'killFilt') ? this.parentNode.parentNode.firstChild.defaultValue : this.getAttribute('optName');
                    this.parentNode.parentNode.firstChild.setAttribute('optName',    (this.className == 'killFilt') ? false : this.getAttribute('optName'));
                    this.parentNode.parentNode.firstChild.setAttribute('optValue',   (this.className == 'killFilt') ? false : this.getAttribute('optValue'));
                    this.parentNode.parentNode.firstChild.setAttribute('optCompare', (this.className == 'killFilt') ? false : this.getAttribute('optCompare'));
                  // update filters array
                    classRoot.filters[this.parentNode.parentNode.getAttribute('filterIndex')][1] = (this.className == 'killFilt') ? false : this.getAttribute('optValue')
                    classRoot.filters[this.parentNode.parentNode.getAttribute('filterIndex')][2] = (this.className == 'killFilt') ? false : this.getAttribute('optCompare')
                  // reset classes
                    var allOpts = this.parentNode.getElementsByTagName('li');
                    for (var item = 0; item < allOpts.length-1; item++) { allOpts[item].className = (allOpts[item] == this) ? 'current' : ''; }
                  // show/hide option for filter removal
                    if (this.className == 'killFilt') {
                      this.style.display = 'none';
                    } else {
                      this.parentNode.lastChild.style.display = 'block';
                    }
                  // webkit needs a bit of help resetting the background image ...
                    if (client.engine == 'webkit') { this.onmouseout(); }
                    classRoot.updateContent();
                  }
              }
              list.lastChild.style.display = 'none';
              var select = classRoot.filtParent.appendChild(select);
            // show sub, so we can measure it
              select.childNodes[2].style.display = 'block';
            // get the width of the widest textnode.
              var maxWidth = parseInt(select.firstChild.offsetWidth);
              var allItems = select.getElementsByTagName('li');
              for (var thisItem = 0; thisItem < allItems.length; thisItem++) {  if (allItems[thisItem].offsetWidth != undefined) { var maxWidth = Math.max(maxWidth, allItems[thisItem].offsetWidth); } }
            // hide sub, since we've measured it
              select.childNodes[2].style.display = '';
            // set width by longest text string
              select.style.width = (maxWidth + 30) + 'px';
              list.style.width = (maxWidth + 30) + 'px';
            // hacks for css-challenged windows browsers ...
              if (client.engine == 'msie') {
              // IE 7
                if (thisFilt != 0 && parseInt(client.engRev) > 6) {
                  list.parentNode.style.marginLeft = parseInt(list.parentNode.previousSibling.style.width) + 15 + 'px';
                  list.parentNode.style.marginTop  = 0 - parseInt(list.parentNode.previousSibling.offsetHeight + 10) + 'px';
                }
              // IE 6
                if (parseInt(client.engRev) < 7) {
                  for (var loop = 0; loop < list.childNodes.length; loop++) {
                    list.childNodes[loop].style.width = parseInt(list.parentNode.style.width) - 22 + 'px';
                  }
                }
              }
            }
          }
        //////////////////////////////////////////////////
        ////  POPULATES TABLE CONTENT ANEW            ////
        //////////////////////////////////////////////////
          classRoot.fillTable = function(contData) {
            if(contData && typeof(contData) == 'string') {
              if (contData.indexOf('I\'m') != -1) { contData = contData.split('I\'m').join('I am'); }
              try { contData = eval(contData); } catch (e) {}
            }
            if (contData && classRoot.proxy)  { classRoot.proxy(contData); }
            if (contData && typeof(contData[0]) != 'undefined' && typeof(contData[0]) == 'boolean') { contData = contData[1]; }
          // use new data if supplied
            if (contData) { classRoot.contData = contData; }

                        classRoot.contData = classRoot.sortIgnoringTags(classRoot.contData);

          // strip all content rows from table
            var allRows   = classRoot.table.getElementsByTagName('tr');
            for (var loop = allRows.length-1; loop > 0; loop--) { classRoot.table.removeChild(allRows[allRows.length-1]); }

          // write in new content/or error if no content
            var useData = classRoot.contData;
                        if (classRoot.sortDir == 'rev') {
                            // create reversed data
                            useData = [];
                            for (var row in classRoot.contData) {
                                useData.push(classRoot.contData[classRoot.contData.length - row - 1]);
                            }
                        }
            if (useData.length) {
              for (var thisRow in useData) { classRoot.addRow(useData[thisRow], classRoot.table); }
            } else {
              var span           = classRoot.table.getElementsByTagName('tr')[0].childNodes.length
              var row            = document.createElement('tr');
                row.className  = 'noDataError';
              var cell           = document.createElement('td');
                cell           = row.appendChild(cell)
                cell.colSpan   = span;
                cell.innerHTML = 'Sorry, there are no matches for your selection. Please make another choice or <a href="javascript: document.location.href = document.location.href;">reload the page</a> to see the entire list.'
                row            = classRoot.table.appendChild(row);
            }
          // open new cell
            if (typeof(qrystr.opencell) != 'undefined') {
              classRoot.showCell(qrystr.opencell)
            } else {
                            // if there is a has tag specified it will try to open
                            // the table cell with that ID, otherwise it will just
                            // open the first cell
                if (document.location.hash != "") {
                    var id = document.location.hash.replace("#", "");
                    var cell = document.getElementById(id);
                    if (cell) {
                        cell.onclick();
                        window.scroll(0, getCumulativeOffset(cell).y);
                    } else {
                      try { classRoot.table.getElementsByTagName('tr')[1].firstChild.onclick(); } catch(e) {}
                    }
                } else {
                  try { classRoot.table.getElementsByTagName('tr')[1].firstChild.onclick(); } catch(e) {}
                }
            };
          }
        //////////////////////////////////////////////////
        ////  SHOW OR HIDE INFO PANEL FOR ROW         ////
        //////////////////////////////////////////////////
          classRoot.showHide = function(thisRow) {
          // get the basic info
            var infoRow   = thisRow.nextSibling;
            var infoPara  = infoRow.firstChild.firstChild
            var titleCell = thisRow.firstChild;
            var sortCell  = thisRow.getElementsByTagName('td')[classRoot.sortCol];
            var isOpen    = (infoRow.style.display == classRoot.rowProp) ? true : false;
          // toggle inline styles for selected item.
            sortCell.style.background = (isOpen) ? '#fcf8ef' : '#FFFFFF';
            sortCell.style.color      = (isOpen) ? '#3E9A00' : '#003366';
            sortCell.style.fontWeight = (isOpen) ? 'normal'  : 'normal';
            infoRow.style.display     = (isOpen) ? 'none'    : classRoot.rowProp;
          // close inline styles for last item?
            if (classRoot.lastInfo && classRoot.lastSort) {
              classRoot.lastSort.style.background = '#fcf8ef';
              classRoot.lastSort.style.color      = '#3E9A00';
              classRoot.lastSort.style.fontWeight = 'normal';
              classRoot.lastInfo.style.display    = 'none';
            }
          // store references so that we can toggle them closed in the future
            classRoot.lastSort  = (isOpen) ? false : sortCell;
            classRoot.lastInfo  = (isOpen) ? false : infoRow;
          // store firstCell innerHTML so we can reactivate it on resort/filter
            classRoot.infoIdStr = (isOpen) ? false : titleCell.innerHTML;
            classRoot.setButtonWidths(infoRow);
          }
        //////////////////////////////////////////////////
        ////  OPEN A CELL FROM QUERYSTRING            ////
        //////////////////////////////////////////////////
          classRoot.showCell = function(cellText) {
            var allRows = classRoot.table.getElementsByTagName('tr');
            for (var loop = 0; loop < allRows.length; loop++) {
              var thisCell = allRows[loop].firstChild;
              if (thisCell.innerHTML == unescape(cellText)) { thisCell.onclick(); }
            }
          }
        //////////////////////////////////////////////////
        ////  ADDS A ROW TO THE TABLE                 ////
        //////////////////////////////////////////////////
          classRoot.addRow    = function(rowData, tableObj) {
          // some dom stuff
            var row     = document.createElement('tr');
          // do some prep work
            var headRow = (tableObj.hasChildNodes()) ? false : true;
            var labels  = (typeof(rowData[0]) == 'string') ? rowData : rowData[0];
            var info    = (rowData[1] && typeof(rowData[1]) == 'object') ? rowData[1] : false;
            row.className = (tableObj.hasChildNodes()) ? 'contRow' : 'headRow';
            row = tableObj.appendChild(row);
          // add all cells to row
            for (var col in labels) {
              var cell            = document.createElement('td');
                cell.colIndex   = col;
                cell.sortColumn = (col == classRoot.sortCol) ? true : false;
                cell.className  = (classRoot.mainData[1][col] && !headRow) ? classRoot.mainData[1][col] : '';
            // inline styles for the sorting colum
              if (cell.sortColumn && !headRow) {
                cell.style.background = '#fcf8ef';
                cell.style.color      = '#3E9A00';
                cell.style.fontWeight = 'normal';
              } else if (cell.sortColumn && headRow)  {
                cell.style.color = '#003366';
              }
            // define default cell contents
              if (headRow) {
                var cellContent = function() {
                  var headerTxt           = document.createTextNode(labels[col].toUpperCase());
                  var headerTxt           = cell.appendChild(headerTxt);
                  var headerImg           = document.createElement('img');
                    headerImg.src       = (cell.sortColumn) ? '/global/assets/images/dyntable/dynTable-wgtSortPos.gif' : '/global/assets/images/dyntable/dynTable-wgtNoSort.gif';
                    headerImg.className = 'sortPointer';
                  var headerImg           = cell.appendChild(headerImg);
                }
              } else {
                var cellContent = function() {
                    var label = labels[col];
                    label = label.replace(/<[^>]+>/ig, '');
                    label = label.replace(/\&[\w|\#]+\;/ig, '');
                    cell.id = label.replace(/[^\w]*/ig, '');
                    cell.innerHTML = labels[col];
                }
              }
              if (!headRow) {
                  cell.onclick   = function() {
                  // handle behaviour by class here,
                  // you can include/exclude expansion handling on a case by case basis
                    switch(this.className) {
                      case '':
                        classRoot.showHide(this.parentNode);
                      break;
                      case 'thrillRating':
                        classRoot.showHide(this.parentNode);
                      break;
//                      case 'height':
//                        classRoot.showHide(this.parentNode);
//                      break;
                      case 'flashPass':
                        classRoot.showHide(this.parentNode);
                      break;
                    }
                  }
                // override default cell content by class
                  switch(cell.className) {
                    case 'thrillRating':
                      var cellContent = function() {
                        var ratingImg     = document.createElement('img');
                          ratingImg.src = '/global/assets/images/icon/thrillRating-' + labels[col] + '.gif';
                          ratingImg     = cell.appendChild(ratingImg);
                        var ratingTxt     = document.createTextNode(labels[col].toUpperCase());
                          ratingTxt     = cell.appendChild(ratingTxt);
                      }
                    break;
//                    case 'height':
//                      var cellContent = function() {
//                        var thisLbl       = (labels[col].indexOf(' ') == -1) ? labels[col] : labels[col].split(' ')[1];
//                        cell.innerHTML    = (thisLbl == 'none' || thisLbl == '' ||  parseInt(thisLbl) == 0) ? 'none' : thisLbl + '&rdquo;';
//                      }
                    break;
                    case 'flashPass':
                      var cellContent = function() {
                        var thisLbl       = labels[col];
                        cell.innerHTML    = (thisLbl.toLowerCase() == 'yes') ? thisLbl : '&nbsp;';
                      }
                    break;
                  }
              } else {
              // header behaviours
                cell.onclick = function() {
                  var allRows   = classRoot.table.getElementsByTagName('tr');
                  var headCols  = this.parentNode.childNodes;
                  for (var col in headCols) { if (headCols[col] == this) { var thisCol = col; break; } }
                  var sortCol   = (this == this.parentNode.childNodes[classRoot.sortCol]) ? true : false;
                // reverse current sort column
                  if (sortCol) {
                  // set sort reversal flag
                    classRoot.sortDir = (classRoot.sortDir == 'rev') ? 'fwd' : 'rev';
                  // change header styles
                    var headCell     = classRoot.table.getElementsByTagName('tr')[0].getElementsByTagName('td')[classRoot.sortCol];
                    var headWdgt     = headCell.getElementsByTagName('img')[0];
                      headWdgt.src = (headWdgt.src.indexOf('/global/assets/images/dyntable/dynTable-wgtSortPos.gif') != -1) ? '/global/assets/images/dyntable/dynTable-wgtSortRev.gif' : '/global/assets/images/dyntable/dynTable-wgtSortPos.gif';
                  // repopulate
                    classRoot.fillTable()
                // set new sort column.
                  } else {
                  // new columns always begin sorted forward
                    classRoot.sortDir   = 'fwd';
                  // clear old sort col styles
                    this.parentNode.childNodes[classRoot.sortCol].style.color   = '';
                    this.parentNode.childNodes[classRoot.sortCol].lastChild.src = '/global/assets/images/dyntable/dynTable-wgtNoSort.gif';
                  // assign new sort col
                    classRoot.sortCell = this;
                    classRoot.sortCol  = this.colIndex;
                    this.lastChild.src = '/global/assets/images/dyntable/dynTable-wgtSortPos.gif';
                    this.style.color   = '#003366';
                  // sort and fill
                    classRoot.fillTable(false);
                  }
                }
              }
            // if a width is specified in the CMS, add it inline
              if (classRoot.mainData[2][col]) { cell.style.width = classRoot.mainData[2][col] + 'px'; }
            // set cell content and add to row ...
              cellContent();
              cell = row.appendChild(cell);
            }
            if (info) { classRoot.addInfo(info, labels.length); }

            handleLinkage();
          }
        //////////////////////////////////////////////////
        ////  ADD INFO ROW IF APPLICABLE              ////
        //////////////////////////////////////////////////
          classRoot.addInfo = function(info, span) {
            var para                  = document.createElement('p');
            var link                  = document.createElement('a');
              link.className        = 'itemLink'
              link.setAttribute('name', '?LPOS=main');
            var optionalLink          = document.createElement('a');
              optionalLink.className = 'itemLink';
              optionalLink.setAttribute('name', '?LPOS=main');
            var buttons               = document.createElement('p');
              buttons.className     = 'button';
            var close                 = document.createElement('a');
              close.className       = 'closeBtn';
              close.innerHTML       = '&nbsp;';
              close.onclick         = function() { this.parentNode.parentNode.previousSibling.firstChild.onclick() };
            var imgDiv                = document.createElement('div');
              imgDiv.className      = 'imgWrapper';
            var infoDiv               = document.createElement('div');
                infoDiv.className     = 'eventWrapper';
            var img                   = document.createElement('img');
            var row                   = document.createElement('tr');
              row.className         = 'infoRow';
            var cell                  = document.createElement('td');
              cell.colSpan          = span;
            if (info[0]) {
                infoDiv.innerHTML = info[0];
            }
            if (info[1]) {
                            infoDiv.appendChild(document.createElement('br'));
              var span = document.createElement('span');
                span.className = 'buttonWrap';
                span = buttons.appendChild(span);
              var linkSpan = document.createElement('span');
                linkSpan = link.appendChild(linkSpan);
                linkSpan.innerHTML = info[1][0];
              link.href    = info[1][1];
              link         = span.appendChild(link);
            }
            if (info[2]) {
                var linkInfo = info[2];
              var span = document.createElement('span');
                span.className = 'buttonWrap';
                span = buttons.appendChild(span);
              var linkSpan = document.createElement('span');
                linkSpan = optionalLink.appendChild(linkSpan);
                linkSpan.innerHTML = linkInfo[0];

              var re = /&rsquo;(\w*)&rsquo;\, &rsquo;(\w*)&rsquo;\, &rsquo;keyword: (\w*)&rsquo;/;

              if (re.test(linkInfo[1])) {
                  var matches = linkInfo[1].match(re);
                  try {
                      optionalLink.onclick = function() {
                          goLink(matches[1], matches[2], "keyword: " + matches[3]);
                          return false;
                      }
                  } catch (e) {

                  }
              } else if (linkInfo[1].indexOf("javascript:goLink") != -1) {
                  var onclick = info[2][1];
                  onclick = onclick.replace(/Season Passes/ig, 'SP');
                  onclick = onclick.replace(/Play Passes/ig, 'PP');
                  onclick = onclick.replace(/&rsquo;/ig, "'");
                optionalLink.setAttribute("onClick", unescape(onclick));
              } else if (linkInfo[1].indexOf("global:") != -1) {
                  var href = linkInfo[1].replace(/global:/ig, '');
                  optionalLink.href = href;
              } else {
                optionalLink.href = "/" + parkname + info[2][1];
              }
              if (linkInfo.length >= 3 && linkInfo[2] == "new-window") {
                  optionalLink.setAttribute("target", "_blank");
              }
              optionalLink = span.appendChild(optionalLink);
            }
            if (info[4]) {
              var span               = document.createElement('span');
                span.className     = 'buttonWrap';
              var fun               = document.createElement('a');
                fun.onclick       = function() { eval(info[4]) }
                fun.className     = 'addFunPlan'
              var funSpan           = document.createElement('span');
                funSpan           = fun.appendChild(funSpan);
                funSpan.innerHTML = 'ADD TO FUN PLANNER';
              fun = span.appendChild(fun);
              span = buttons.appendChild(span);
            }
            var botGap = document.createElement('div');
              botGap.className = 'bottom-gap';
              botGap.style.marginBottom = (client.engine == 'msie' && parseInt(client.engRev) >= 7) ? '-10px' : '-22px';
              botGap = buttons.appendChild(botGap);
            if (info[3]) {
              img.src = info[3];
              img = imgDiv.appendChild(img);
                            imgDiv   = para.appendChild(imgDiv);
            } else {
                infoDiv.style.width = "auto";
                            // buttons.style.width = "auto";
            }
            infoDiv  = para.appendChild(infoDiv);
            buttons  = para.appendChild(buttons);
            para     = cell.appendChild(para);
            close    = cell.appendChild(close);
            var cell = row.appendChild(cell);
            row      = classRoot.table.appendChild(row);
            var spans = buttons.childNodes;
            if (row.previousSibling.firstChild.innerHTML == classRoot.infoIdStr) { row.previousSibling.firstChild.onclick() }
            handleLinkage();
          }
          classRoot.setButtonWidths = function(element) {
            if (element === undefined) {
              element = classRoot.table;
            }
            var spans = element.getElementsByTagName("span");
            for (var i = 0; i < spans.length; i++) {
              var span = spans[i];
              if (span.className == "buttonWrap" && span.style.width == 0) {
                var width = span.offsetWidth + 12;
                if (width > 0) {
                  span.style.width = width + "px";
                }
              }
            }
          }
        //////////////////////////////////////////////////
        ////  REVERSE TABLE ROW DIRECTIONS            ////
        //////////////////////////////////////////////////
          classRoot.invert = function() {
            var headCell     = classRoot.table.getElementsByTagName('tr')[0].getElementsByTagName('td')[classRoot.sortCol];
            var headWdgt     = headCell.getElementsByTagName('img')[0];
              headWdgt.src = (headWdgt.src.indexOf('/global/assets/images/dyntable/dynTable-wgtSortPos.gif') != -1) ? '/global/assets/images/dyntable/dynTable-wgtSortRev.gif' : '/global/assets/images/dyntable/dynTable-wgtSortPos.gif';
          }
        // start it up
          classRoot.initTable();
        // setter for external function
          classRoot.setBaseReq = function(url) {
            classRoot.baseReq = url;
          }

        //////////////////////////////////////////////////
        ////  POST TABLE DATA RETRIEVAL FUNCTIONS     ////
        //////////////////////////////////////////////////
                    classRoot.trim = function(str) {
                        return str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
                    }

                    classRoot.sortCompareFunc = function(a, b) {

                        var year = new Date().getFullYear();
                        var sortColName = classRoot.mainData[0][classRoot.sortCol];

                        if (sortColName.toLowerCase() == "date") {
                            a = classRoot.buildDate(a[0][classRoot.sortCol]);
                            b = classRoot.buildDate(b[0][classRoot.sortCol]);
                        } else {
                            a = classRoot.trim(a[0][classRoot.sortCol].replace(/<.+?>/, '').replace(/<[\/].+?>/, '').toLowerCase());
                            b = classRoot.trim(b[0][classRoot.sortCol].replace(/<.+?>/, '').replace(/<[\/].+?>/, '').toLowerCase());
                        }

                        return a < b ? -1 : (a > b ? 1 : 0);
                    }

                    /*
                        Sort contData, ignoring starting and ending tags on each field
                        used in comparsion (e.g. '<i>value</i>' would be treated as 'value').

                        Assumed contData structure = [
                            [
                                [val_111, val_112, etc.]
                                [val_121, val_122, etc.]
                            ]
                        ]
                    */
                    classRoot.sortIgnoringTags = function(contData) {
                        contData.sort(classRoot.sortCompareFunc);
                        return contData;
                    }

                    classRoot.buildDate = function(dateString) {
                        var startDateString   = dateString.replace(/\ \-\ \d{1,2}\/\d{1,2}/, "");
                        var endDateString = dateString.replace(/\d{1,2}\/\d{1,2}\ \-\ /, "");
                        var year            = new Date().getFullYear();
                        var nextYear        = new Date().getFullYear() + 1;

                        var startDate = new Date(startDateString + "/" + year);
                        var endDate   = new Date(endDateString + "/" +  year);
                        if (endDate < startDate) {
                            endDate = new Date(endDateString + "/" + nextYear);
                        }
                        var curDate   = new Date();
                        var date      = null;
                        if (startDate == endDate && startDate < curDate) {
                            date = new Date(startDateString + "/" + nextYear)
                        } else if (startDate < curDate && endDate < curDate) {
                            date = new Date(startDateString + "/" + nextYear);
                        } else {
                            return startDate;
                        }

                        return date;
                    }
                }

                var getCumulativeOffset = function (obj) {
                    var left, top;
                    left = top = 0;
                    if (obj.offsetParent) {
                        do {
                            left += obj.offsetLeft;
                            top  += obj.offsetTop;
                        } while (obj = obj.offsetParent);
                    }
                    return {
                        x : left,
                        y : top
                    };
                };




