window.onerror = null;    //fixes NIS error suppresion
//extend the string to support trimming
if(!String.prototype.trim){
    String.prototype.trim = function(){
        return this.replace(/^\s+|\s+$/gi,"");
    }
}

//Very basic html escaping function
function html_escape(arg){
    if(!arg)return "";
    return arg.replace("&","&amp;").replace("<","&lt;").replace(">","&gt;");
}
/* Includes additional scripts
     - The content of the script fires only 
       after this entire script is run */
function include_script(file,mime_type){
    if(!mime_type)
        mime_type = "text/javascript";
    document.writeln("<script type=\"" + mime_type + "\" src=\"" + file + "\"><\/script>");
}
//Submits the search form passed to the function
function submit_search(form_name){
    if(document.forms[form_name]){
        document.forms[form_name].submit();
        return false;
    }else{
        return true;    //couldn't find form, do clickthru
    }
}
//Initializes the search events
function search_init(){
    var a;
    if(a = document.getElementById('topsearch')){
        add_event(a,"click",do_search);
    }
    if(a = document.getElementById('bottomsearch')){
        add_event(a,"click",do_search);
    }
}
//Executes the search based on the object firing the event
function do_search(){
    var obj = (document.Browser.IsIE ? window.event.srcElement : this);
    switch(obj.id){
        case "topsearch":
            return submit_search('searchtop');
        case "bottomsearch":
            return submit_search('searchbottom');
        default:
            return true;
    }
}
//dummy image preloader
document.preloadedImages = [];    //create a document-level array of the images
function preload_image(s){
    if(document.preloadedImages[s]){
        return;    //already preloading/preloaded
    }
    var i = new Image();
    i.src = s;
    document.preloadedImages[s] = i;
}
//Adds an event to the OnLoad event.
function add_load_event(func){
    add_event(window,"load",func);
}
//Attaches event callbacks functions to an object
function add_event(obj, ev, func){
    if(!obj)return;    //no object
    if(obj.addEventListener){
        obj.addEventListener(ev,func,false);
    }else if(obj.attachEvent){
        obj.attachEvent("on"+ev,func);
    }else{
        //Out of luck.  Most (if not all) browsers
        //support either of the above event models.
    }
}
//Include additional javascript files

//attach the search initialization
add_load_event(search_init);
 


/**************************************
File:    browser.js
Author:    Matt Meyer
Date:    2007.05.24
Description:
    Detects browser information and 
    features.
**************************************/
//Owner object
Browser.prototype.Owner = false;
//Browser Types
Browser.prototype.IsIE = false;
Browser.prototype.IsOpera = false;
Browser.prototype.IsFirefox = false;
Browser.prototype.IsNetscape = false;
Browser.prototype.IsSafari = false;
Browser.prototype.IsOther = false;
//Capabilities
Browser.prototype.HasDOM = false;
Browser.prototype.HasJava = false;
Browser.prototype.HasCookies = false;
Browser.prototype.HasActiveX = false;
//Common Plugins
Browser.prototype.HasFlash = false;
Browser.prototype.HasAcrobat = false;
Browser.prototype.HasQuickTime = false;
Browser.prototype.HasMediaPlayer = false;
Browser.prototype.IsLoaded = false;
//Browser/OS Version
Browser.prototype.Version = 0.0;
Browser.prototype.MajorVersion = 0;
Browser.prototype.MinorVersion = 0;
Browser.prototype.OperatingSystem = "";
function Browser(Owner){
    //so I can access config and what not
    if(Owner){
        this.Owner = Owner;
    }
    
    var info = this.GetUserAgentInfo();
    var v;    //used in version detection
    var b = false;    //flag for detecting browse
    
    //Attempts to parse the info in the user agent
    //segments.  
    for(var i = 0; i < info.length; i++){
        if(info[i].indexOf("MSIE")!=-1){    //IE
            b = true;
            this.IsIE = true;
            v = info[i].split(" ")[1];
            this.Version = v;
            v = v.split(".");
            this.MajorVersion = v[0];
            this.MinorVersion = v[1];
        }else if(info[i].indexOf("Opera")!=-1){    //Opera
            b = true;
            this.IsOpera = true;
            v = info[i].split("/")[1];
            this.Version = v;
            v = v.split(".");
            this.MajorVersion = v[0];
            this.MinorVersion = v[1];
        }else if(info[i].indexOf("Firefox")!=-1){    //Firefox
            b = true;
            this.IsFirefox = true;
            v = info[i].split("/")[1];
            this.Version = v;
            v = v.split(".");
            this.MajorVersion = v[0];
            this.MinorVersion = v[1];
        }else if(info[i].indexOf("Safari")!=-1){    //Safari
            b = true;
            this.IsSafari = true;
            v = info[i].split("/")[1];
            this.Version = v;
            v = v.split(".");
            this.MajorVersion = v[0];
            this.MinorVersion = v[1];
        }else if(info[i].indexOf("Netscape")!=-1){    //Navigator
            b = true;
            this.IsNetscape = true;
            v = info[i].split("/")[1];
            this.Version = v;
            v = v.split(".");
            this.MajorVersion = v[0];
            this.MinorVersion = v[1];
        }else if(info[i].indexOf("Windows")!=-1){    //Windows (OS)
            this.OperatingSystem = info[i];
        }else if(info[i].indexOf("OS X")!=-1){        //Mac (OS)
            this.OperatingSystem = info[i];
        }
    }
    //Check if we've detected what browser
    if(!b){
        this.IsOther = true;
    }
    //Capability detection
    this.HasJava = navigator.javaEnabled();
    this.HasCookies = navigator.cookieEnabled;
    this.HasActiveX = window.ActiveXObject ? true : false;
    if(document.getElementById)
        this.HasDOM = true;
    if(this.IsIE){
        //Use special function for detecting IE plugins
        //since it doesn't use the plugins array.
        this.HasFlash = this.DetectIePlugin("ShockwaveFlash.ShockwaveFlash");
        this.HasAcrobat = this.DetectIePlugin("PDF.PdfCtrl");
        this.HasQuickTime = this.DetectIePlugin("QuickTimeCheckObject.QuickTimeCheck");
        this.HasMediaPlayer = this.DetectIePlugin("MediaPlayer.MediaPlayer");
    }else{
        if(navigator.plugins){
            for(var i = 0; i < navigator.plugins.length; i++){
                if(navigator.plugins[i].name.indexOf("Flash")!=-1)
                    this.HasFlash = true;
                else if(navigator.plugins[i].name.indexOf("Acrobat")!=-1)
                    this.HasAcrobat = true;
                else if(navigator.plugins[i].name.indexOf("QuickTime")!=-1)
                    this.HasQuickTime = true;
                else if(navigator.plugins[i].name.indexOf("Windows Media Player")!=-1)
                    this.HasMediaPlayer = true;
            }
        }
    }
    //just to be stateful
    this.IsLoaded = true;
}
//Function specifically for detecting pluins in IE by
//created an ActiveX object for them.
Browser.prototype.DetectIePlugin = function(name){
    var t;
    for(var i = 1; i < 10; i++){
        try{
            t = new ActiveXObject(name + "." + i);
            return true;
        }catch(e){
        }
    }
    return false;
}
//Retreives the UserAgent string and makes a best 
//attempt to split up into relevant chunks
Browser.prototype.GetUserAgentInfo = function(){
    var ua = navigator.userAgent;
    var uainf = [];    //info
    var s = 0,    //start
        i = 0;    //index
    var sc = " (",    //split characters
        v = "";    //value
    while(i < ua.length){
        if(sc.indexOf(ua.charAt(i))!=-1){
            if(s!=i){
                v = ua.substr(s,i-s).trim();
                if(v.length>0){
                    uainf.push(v);
                }
            }
            s = i+1;
            if(ua.charAt(i)=="("){
                sc = ";)";
            }else if(ua.charAt(i)==")"){
                sc = " (";
            }
        }
        i++;
    }
    if(s!=i){    //last value
        v = ua.substr(s,i-s).trim();
        if(v.length>0){
            uainf.push(v);
        }
    }
    return uainf;
}
//Create a browser object in the document model
document.Browser = new Browser();


/**************************************
File:    site.js
Author:    Matt Meyer
Date:    2007.05.24
Description:
    Site utility object for reading and
    creating queries and cookies.  Also
    stores information about the url and
    page.  
    
    Currently does not access form data.
ToDo:
    Fix Port Bug (low priority)
**************************************/
//Owner object
Site.prototype.Owner = false;
//URL properties
Site.prototype.Url = "";
Site.prototype.RelativeUrl = "";
Site.prototype.QueryString = "";
Site.prototype.Protocol = "";
Site.prototype.Port = "";
Site.prototype.Hostname = ""; //hostname
Site.prototype.Path = "";    //path
Site.prototype.File = "";    //file name
Site.prototype.PathArray = [];    //segmented path
//Query String and Cookie properties
Site.prototype.QueryValues = [];
Site.prototype.Cookies = [];    //put this in for easier management
//Constructor
function Site(Owner){
    //assign owner if applicable
    if(this.Owner){
        this.Owner = Owner;
    }
    
    this.Url = location.href;
    //QS is needed to construct the RealtiveUrl
    if(this.Url.indexOf("?")!=-1)
        this.QueryString = this.Url.substr(this.Url.indexOf("?"));
    this.RelativeUrl = location.pathname + this.QueryString;
    
    //Host, Port, Path
    this.Protocol = location.protocol + "//";
    this.Hostname = location.hostname;
    
    //Known Bug: If an alternate port is used via http://whatever:port, this fails
    if((this.Port = location.port).length==0){
        this.Port = (this.Protocol=="http://" ? 80 : 443);
    }
    
    //parses the path info
    var p = location.pathname;
    if(p.length>0){
        if(p.substr(p.length-1)!="/"){
            var l = p.length-1;
            while(l >= 0 && p.charAt(l)!="/"){
                l--;
            }
            if(l==-1){
                //here just in case.
            }else{
                p = p.substr(0,l+1);
            }
        }
        this.Path = p;
        if(this.Path!="/"){
            this.PathArray = this.Path.substr(1,this.Path.length-2).split("/");
        }
    }
    //detects the file name
    this.File = this.Url.substr(this.Protocol.length + this.Hostname.length + this.Path.length);
    this.File = this.File.substr(0,this.File.length - this.QueryString.length);
    
    //load cookies and queries
    this.LoadQueryValues();
    this.LoadCookies();
}
//Parses the query string and stores name=>value pair
// Receives optional pair delimiter ('pd') and value delimiter ('vd')
Site.prototype.LoadQueryValues = function(pd,vd){
    //load default delimiters
    if(!pd)
        pd = "&";
    if(!vd)
        vd = "=";
        
    this.QueryValues = [];
    
    var qs = this.QueryString;
    if(qs.length==0)return;
    qs = qs.substr(1);    //strip the '?'
    
    var sets = qs.split(pd);
    for(var i = 0; i < sets.length; i++){
        var idx = sets[i].indexOf(vd);
        if(idx==-1){
            //no value (such as a flag or something)
            //set to true to signify it's defined
            this.QueryValues[unescape(sets[i])] = true;
            continue;
        }
        //split
        var k = unescape(sets[i].substr(0,idx));
        var v = unescape(sets[i].substr(idx+1));
        //add to arrays
        this.QueryValues[k] = v;
    }
}
//Crafts a query string from the name/value pairs.
// Receives optional pair delimiter ('pd') and value delimiter ('vd')
Site.prototype.CreateQueryString = function(pd,vd){
    //load default delimiters
    if(!pd)
        pd = "&";
    if(!vd)
        vd = "=";
        
    var qs = "?";
    for(var key in this.QueryValues){
        qs += escape(key) + vd + escape(this.QueryValues[key]) + pd;
    }
    qs = qs.substr(0,qs.length-pd.length);    //strips the last delimiter
    
    return qs;
}
//Gets a cookie value
Site.prototype.GetCookie = function(name){
    return this.Cookies[name];
}
//Set a cookie value (option expiration, domain, path, and secure flag are available)
Site.prototype.SetCookie = function(name,value,expiration,domain,path,secure){
    //create the real cookie for the browser
    var c = escape(name) + "=" + escape(value);
    if(expiration)
        c += "; expires=" + expiration.toUTCString();
    if(domain)
        c += "; domain=" + domain;
    if(path)
        c += "; path=" + path;
    if(secure)
        c += "; secure";
    document.cookie = c;
    
    //manage the internal cookie array for the site object
    if(expiration < Date()){
        delete this.Cookies[name];
    }else{
        this.Cookies[name] = value;
    }
}
//Removes a cookie
Site.prototype.DeleteCookie = function(name){
    this.SetCookie(name,false,new Date(0));
}
//Loads the cookie object into a name=>value array.
Site.prototype.LoadCookies = function(){
    var c = document.cookie;
    this.Cookies = [];    //clears the array
    if(c.length == 0)
        return;
    c = c.split(";");
    //now we have name/value pairs
    for(var i = 0; i < c.length; i++){
        c[i] = c[i].trim();
        if(c[i].length==0)
            continue;
        var idx = c[i].indexOf("=");
        if(idx==-1)    //very akward
            continue;
        var k = unescape(c[i].substr(0,idx));
        var v = unescape(c[i].substr(idx+1));
        this.Cookies[k] = v;
    }
}
//Removes all cookies
Site.prototype.ClearCookies = function(){
    for(var c in this.Cookies){
        this.DeleteCookie(c);
    }
}
//Create a new site object for use
document.Site = new Site(); 
 

/**************************************
File: dom_assist.js
Author: Matt Meyer
Date: 2007.05.25
Description:
    Assists with the DOM navigation
    due to no implementation of an
    "ignoreWhitespace" option.  These
    functions navigate the DOM tree 
    skipping the whitespace nodes.
    
    I skipped a textNode check since
    DOM's innerText/innerHTML could 
    be used instead.  It would be 
    trivial to add.
**************************************/
//Fetches the next sibling node
function domNextSibling(obj){
    var o = false;
    if(obj){
        o = obj;
        do{
            o = o.nextSibling;
            if(o==null)return false;
        }while(o.nodeType!=1);
    }
    return o;
}
//Fetches the previous sibling node
function domPrevSibling(obj){
    var o = false;
    if(obj){
        o = obj;
        do{
            o = o.previousSibling;
            if(o==null)return false;
        }while(o.nodeType!=1);
    }
    return o;
}
//Fetches the first child node
function domFirstChild(obj){
    var o = obj.firstChild;
    if(o==null)return false;    //no children
    if(o.nodeType==1)return o;    //is a real node
    return domNextSibling(o);    //search for the first real node
}
//Fetches the last child node.
function domLastChild(obj){
    var o = obj.lastChild;
    if(o==null)return false;    //no children
    if(o.nodeType==1)return o;    //is a real node
    return domPrevSibling(o);    //search for the last real node
}
 