﻿// This source code is owned by Ephibian, Inc.
// Any use of this software requires the explicit
// permission of Ephibian, Inc.
 
// Copyright 1997-2008, Ephibian Inc.
// All Rights Reserved.

// SolidNav.js
// This script will generate css styles that turn an unordered list and
// a strategically created image into a navigation control.
// It does this by assigning each anchor the same background image
// and shifting it left.  The "highlighted" anchor is achieved by
// shifting the image up.

// Your HTML should have an unordered list with an id.
// Each list item should have a unique class.  Why not an id?
// Because your <body> should have an id that will match the class on
// one of your list items to highlight for that page (and you can't
// have two ids on a page with the same value).

// HTML example:
// <ul id="menu_nav">
//   <li class="item1"><a href="?PAGEID=item1">Item 1</a></li>
//   <li class="item2"><a href="?PAGEID=item2">Item 2</a></li>
//   <li class="item3"><a href="?PAGEID=item3">Item 3</a></li>
//   <li class="item4"><a href="?PAGEID=item4">Item 4</a></li>
//   <li class="item5"><a href="?PAGEID=item5">Item 5</a></li>
//   <li class="item6"><a href="?PAGEID=item6">Item 6</a></li>
//   <li class="item7"><a href="?PAGEID=item7">Item 7</a></li>
// </ul>

// Javascript must be placed *after* the HTML:
// <script type="text/javascript" src="SolidNav.js"></script>
// <script type="text/javascript">
//   var solidNav = new SolidNav('menu_nav');
//   solidNav.setDebug(0);
//   solidNav.setPageId('item1');
//   solidNav.setHeight(31);
//   solidNav.setWidth(520);
//   solidNav.setImage('/images/menu.jpg');
//   solidNav.setStartX(0);
//   solidNav.setStartY(3);
//   solidNav.setShiftX([63,67,91,79,73,64,82]);
//   solidNav.setShiftY(33);
//   solidNav.render();
// </script>

function SolidNav(navId) {
	this.navId   = navId;
	this.navList = document.getElementById(navId);
	this.imgUrl  = '';
	this.height  = 0;
    this.width   = 0;
	this.startX  = 0;
	this.startY  = 0;
	this.shiftDistanceX = 0;
	this.shiftDistanceY = 0;
	this.pageId  = '';
    this.ie      = (document.all);
    this.debug   = 0;
    this.css = makeStyleSheet();
    function makeStyleSheet() {
        var navCss = document.createElement('style');
        navCss.type = 'text/css';
        navCss.rel = 'stylesheet';
        navCss.media = 'screen';
        navCss.title = 'navCss';
        document.getElementsByTagName("head")[0].appendChild(navCss);
        // loop in reverse, the stylesheet we just created should be last
        for(var i = document.styleSheets.length - 1; i >= 0; i--) {
            var css = document.styleSheets[i];
            if(css.title == 'navCss') {
                return css;
            }
        }
    }
}

SolidNav.prototype.setImage = function(imgUrl) {
  this.imgUrl = imgUrl;
}

SolidNav.prototype.setHeight = function(height) {
  this.height = height;
}

SolidNav.prototype.setWidth = function(width) {
  this.width = width;
}

SolidNav.prototype.setStartX = function(startX) {
  this.startX = startX;
}

SolidNav.prototype.setStartY = function(startY) {
  this.startY = startY;
}

SolidNav.prototype.setShiftX = function(shiftDistanceX) {
  this.shiftDistanceX = shiftDistanceX;
}

SolidNav.prototype.setShiftY = function(shiftDistanceY) {
  this.shiftDistanceY = shiftDistanceY;
}

SolidNav.prototype.setPageId = function(pageId) {
  this.pageId = pageId;
}

SolidNav.prototype.setDebug = function(debug) {
  this.debug = debug;
}

// addStyle will add a css style to the styles created by this script
SolidNav.prototype.addStyle = function(selector, rule) { 
  this.ie ? this.css.addRule(selector, rule) : this.css.insertRule(selector + '{ ' + rule + ' }', this.css.cssRules.length);
}

// showAllStyles will append all styles to the navList
// this is primarily used for debugging
SolidNav.prototype.showAllStyles = function() {
  this.navList.appendChild(this.getAllStyles());
}

// getAllStyles will create a div dynamically
// its contents show what css styles were dynamically created by this script  
SolidNav.prototype.getAllStyles = function() {
  var styles = document.createElement('div');
  styles.style.color = '#000';
  styles.style.backgroundColor = '#ccc';
  styles.style.border = '1px solid #000';
  styles.style.fontFamily = 'monospace';
  styles.style.fontSize = '0.8em';
  styles.style.position = 'relative';
  styles.style.top = '5em';
  var rules = this.ie ? this.css.rules : this.css.cssRules;
		
	for(var i = 0; i < rules.length; i++) {
	  var currSelector = rules[i].selectorText.toLowerCase();		  
	  var prevSelector = null;
	  var nextSelector = null;
	  if(i > 0) {
	    prevSelector = rules[i-1].selectorText.toLowerCase();
	  }
	  if(i + 1 < rules.length) {
	    nextSelector = rules[i+1].selectorText.toLowerCase();
	  }
	  if(!prevSelector || prevSelector != currSelector) {
  	  styles.appendChild(document.createTextNode(currSelector + ' {'));
     	styles.appendChild(document.createElement('br'));
  	}
 	  styles.appendChild(document.createElement('nbsp'));
  	styles.appendChild(document.createTextNode('\u00a0\u00a0' + rules[i].style.cssText.toLowerCase()));
  	if(this.ie) {
  	  styles.appendChild(document.createTextNode(';')); // ie doesn't print semi-colons in cssText
  	}
 	  styles.appendChild(document.createElement('br'));
	  if(!nextSelector || nextSelector != currSelector) {
  	  styles.appendChild(document.createTextNode('}'));
  	  styles.appendChild(document.createElement('br'));
  	  styles.appendChild(document.createElement('br'));
  	}
	}
	return styles;
}

// renderNav will generate all the css styles needed for this script to work
SolidNav.prototype.render = function() {
  // generate the styles needed for the ul
  this.addStyle('#' + this.navId, 'height: ' + this.height + 'px;');
  this.addStyle('#' + this.navId, 'list-style-type: none;');
  this.addStyle('#' + this.navId, 'margin: 0;');
  this.addStyle('#' + this.navId, 'position: relative;');
  this.addStyle('#' + this.navId, 'width: ' + this.width + 'px;');
  
  this.addStyle('#' + this.navId + ' a', 'background-image: url(' + this.imgUrl + ');');
  this.addStyle('#' + this.navId + ' a', 'height: ' + this.height + 'px;');
  this.addStyle('#' + this.navId + ' a', 'position: absolute;');
  this.addStyle('#' + this.navId + ' a', 'text-decoration: none;');
  this.addStyle('#' + this.navId + ' a', 'text-indent: -9999px;');
  this.addStyle('#' + this.navId + ' a', 'top: 0;');

  // generate the styles needed for the list items
  var navItems = this.navList.getElementsByTagName('li');
  for(var i = 0; i < navItems.length; ++i) {
	  var shiftX = 0;
	  for (var j = 0; j < i; j++) {
	    if (this.shiftDistanceX instanceof Array) {
	      shiftX += this.shiftDistanceX[j];
		}
		else {
	      shiftX += this.shiftDistanceX;
	  	}
	  }

	  var positionX = (-1 * (this.startX)) - (shiftX);
	  var positionY = (-1 * (this.startY));
		
	  var positionYHilight = positionY - this.shiftDistanceY;
	  var itemWidth = this.shiftDistanceX instanceof Array ? this.shiftDistanceX[i] : this.shiftDistanceX;
	  var itemClass = this.ie ? navItems[i].className : navItems[i].getAttribute('class');
	  if(this.pageId == itemClass) {
        this.addStyle('.' + itemClass + ' a', 'background-position: ' + positionX + 'px ' + positionYHilight + 'px;');
	  }
	  else {
        this.addStyle('.' + itemClass + ' a', 'background-position: ' + positionX + 'px ' + positionY + 'px;');
	  }
      this.addStyle('.' + itemClass + ' a', 'left: ' + shiftX + 'px;');
      this.addStyle('.' + itemClass + ' a', 'width: ' + itemWidth + 'px;');
      this.addStyle('.' + itemClass + ' a:hover', 'background-position: ' + positionX + 'px ' + positionYHilight + 'px;');
  }

  if(this.debug) {
    this.showAllStyles();
  }
}