// JavaScript Document/*** Copyright 1998-2007 Netopia Inc. All Rights Reserved. ***/



var browser = navigator.userAgent.toLowerCase();
var isWindows = (browser.indexOf("windows") != -1);
var isIE = (browser.indexOf("msie") != -1 && browser.indexOf("opera") == -1);
var IEVersion = parseInt(browser.substr(browser.indexOf("msie")+5,1));
var TG_doShowSignIn = false;
var TG_moImgs = new Array();

function doRTEMouseover(imgObj, srcStr){TG_srcOver(imgObj, srcStr);}
function TG_srcOver(imgObj, srcStr)
{
    try 
    {
        srcStr = TG_appendVersion(srcStr, true);
        if (TG_moImgs[srcStr] == null)
        {
            var newImg = new Image();
                newImg.src = srcStr;
            
            TG_moImgs.push(newImg);
            TG_moImgs[srcStr] = TG_moImgs[TG_moImgs.length-1];
        }
    
        imgObj.src = TG_moImgs[srcStr].src;
   }
   catch (e) { imgObj.src = srcStr; }
}

function TG_altSrc(imgObj, srcStr)
{
    if (imgObj.src.indexOf(srcStr) != -1)
        imgObj.onerror = "";
    else
        imgObj.src = srcStr;
}

if (document.images)
{
    var tp = new Image(1,1);
    tp.src = transpix; //precache the transpix img
}

var maxWidth,maxHeight;
function TG_calcMaxWidth()
{
   var bc = document.getElementById('TGBodyContent');
   var bodyOrigin = document.getElementById('TGBodyOrigin');
   var ctrTable = document.getElementById('TGcenteringTable'); 

   if (ctrTable)
   {
       maxHeight = 0;
       maxWidth  = 0;
       
       var pageTags = bc.getElementsByTagName("*");
       var bX = (bodyOrigin ? parseInt(bodyOrigin.style.left, 10) : 0);
       var bY = (bodyOrigin ? parseInt(bodyOrigin.style.top,  10) : 20);
    
       for (var i = 0; i < pageTags.length; i++)
       {
          var curW = (pageTags[i].offsetLeft + pageTags[i].offsetWidth);
          var curH = (pageTags[i].offsetTop +  pageTags[i].offsetHeight);
          if(pageTags[i].parentNode && pageTags[i].parentNode.id == "TGBodyOrigin")
          {
              curW += bX;
              curH += bY;
          }
    
          maxWidth  = curW > maxWidth  ? curW : maxWidth;
          maxHeight = curH > maxHeight ? curH : maxHeight;
       }
   
   }
   else
   {
        PageExtents.calculate(bc, bodyOrigin);
   }  
   
}

function TG_adjustLayout()
{
   var ctrTable = document.getElementById('TGcenteringTable');
   
   if (ctrTable)
   {
        if (!maxWidth)
            TG_calcMaxWidth();
        
        try
        {
            var ctrTable = document.getElementById('TGcenteringTable');
            var ctrDIV = document.getElementById('TGcenteringDIV');
        
            //set the proper width for the centering table if centering is enabled
            if (ctrTable)
            {
                ctrTable.width = maxWidth;
                ctrDIV.style.height = maxHeight + "px";
            }
        }
        catch (e) {}
        
   }
   else
   {
        if (PageExtents.maxWidth == 0)
            TG_calcMaxWidth();
        
        try
        {
            var tgBc = document.getElementById("TGBodyContent");
            
            //set the proper width for the centering table if centering is enabled
            if (tgBc.style.left == "50%")
            {
                tgBc.style.marginLeft = ("-" + Math.floor(PageExtents.maxWidth / 2) + "px");
            }
        }
        catch (e) {}
    }
}

function TG_showSignIn()
{
   var ctrTable = document.getElementById('TGcenteringTable');
   if (ctrTable)
   {
        if (!maxWidth)
            TG_calcMaxWidth();
        
        var maxX = maxWidth;
        var maxY = document.body.scrollHeight;
        var banner = document.getElementById('TGSignInBanner');
        
        if (banner)
        {
    
    
            var bannerX = maxX - banner.offsetWidth;
            var bannerY = maxY;
            banner.style.top =  (bannerY + 25) + "px";
            banner.style.left = (bannerX - 25) + "px";
            banner.style.visibility = "visible";
        }
       
   }
   else
   {
        if (PageExtents.maxWidth == 0)
            TG_calcMaxWidth();
        
        var maxX = PageExtents.maxWidth;
        var maxY = document.body.scrollHeight;
        var banner = document.getElementById('TGSignInBanner');
        
        if (banner)
        {
    
    
            var bannerX = maxX - banner.offsetWidth;
            var bannerY = maxY;
            
            var tgCs = document.getElementById("TGCtrSignIn");
            
            //set the proper width for centering the sign-in logo if centering is enabled
            if (tgCs && tgCs.style.left == "50%")
            {
                tgCs.style.marginLeft = ("-" + Math.floor(PageExtents.maxWidth / 2) + "px");
            }
    
            banner.style.top =  (bannerY + 25) + "px";
            banner.style.left = (bannerX - 25) + "px";
            banner.style.visibility = "visible";
        }
   }
}

function TG_disableForm()
{
    //prevent form submissions on preview window
    var inputs = document.body.getElementsByTagName("INPUT");
    for (var i = 0; i < inputs.length; i++)
    {
        if (inputs[i].getAttribute("type") == "button" && 
            inputs[i].getAttribute("name") == "nxg_SubmitButton")
        {
            inputs[i].onclick = function () {return false};
            inputs[i].disabled = true;
        }
    }
}

function TG_removeLinks()
{
    try
    {
        //prevent hyperlinks from activating in preview window
        var aTags = document.body.getElementsByTagName("A");
        for (var i = 0; i < aTags.length; i++)
        {
            aTags[i].href = "javascript:void(0);";
            aTags[i].target = "_self";
            aTags[i].style.cursor = "default";
        }
    }
    catch(e)
    {
        //do nothing
    }
}


function TG_colorOver(divObj, newColor)
{
    var domEls = null;

    // first look for SPAN tags in the div
    // if div does not contain any, look for A tags
    // if div does not contain any, look for P tags
    //NOTE: I had to re-order the A and P ones to look for A first, because having color on a P set with an A tag inside it, wouldn't recolor text (Issue 1135)
    // if none of these, just re-color the entire div
    domEls = divObj.getElementsByTagName("SPAN");
    if (!domEls || domEls.length == 0)
    {
        domEls = divObj.getElementsByTagName("A");
        
        if (!domEls || domEls.length == 0)
        {
            domEls = divObj.getElementsByTagName("P");
            
            if (!domEls || domEls.length == 0)
            {
                domEls = new Array();
                domEls[0] = divObj;
            }
        }
    }

    if (domEls && domEls.length)
    {
        for (var i = 0; i < domEls.length; i++)
        {
            if (domEls[i].tmpColor)
            {
                domEls[i].style.color = (domEls[i].tmpColor == "none" ? "" : domEls[i].tmpColor);
                domEls[i].tmpColor = null;
            }
            else if (newColor != null)
            {
                domEls[i].tmpColor = (domEls[i].style.color ? domEls[i].style.color : "none");
                domEls[i].style.color = newColor;
            }
        }
    }
}


function TG_doLink(url, target, args)
{
    if (!pv) // if not in preview mode
    {
      url = TG_appendVersion(url, false);

      try 
      {
        if (target == "_self" || target=="" || !target)
        {
            var magicLink = document.getElementById("TGLink");
            
            magicLink.href = url;
            magicLink.target = (target ? target : "_self");
            magicLink.click();
        }
        else
            TG_lnkWin(null, args, url, target);
      } 
      catch (e) 
      {
        if (target == "_self")
            location = url;
        else
            TG_lnkWin(null, args, url, target);
      }
       
    }

    return false;
}

function TG_lnkWin(aTag, args, url, target)
{
    var params = "";

    if (args)
    {
        args = args.split(",");
        
        var features = parseInt(args[0],36);
        var height   = parseInt(args[1],35);
        var width    = parseInt(args[2],34);
        var top      = parseInt(args[3],33);
        var left     = parseInt(args[4],32);
    
        if (height && width)
            params += "height="+height+",width="+width+",";
    
        if ((features&128) == 128)
            params += "top="+((screen.height-height)/2)+",left="+((screen.width-width)/2)+",";
        else if (top && left) 
            params += "top="+top+",left="+left+",";
        
        params += "menubar="+((features&1)/1)+",";
        params += "toolbar="+((features&2)/2)+",";
        params += "location="+((features&4)/4)+",";
        params += "directories="+((features&8)/8)+",";
        params += "status="+((features&16)/16)+",";
        params += "scrollbars="+((features&32)/32)+",";
        params += "resizable="+((features&64)/64);
    }

    if (aTag)
        var newWin = window.open(TG_appendVersion(aTag.href,false),aTag.target,params);
    else
    {
        // do NOT use "_self" as the second arg to window.open as it fails in Firefox
        var newWin = window.open(TG_appendVersion(url, false), (target ? target : "_blank"),params);
    }
    if (window.focus) newWin.focus();
    
    return false;
}

function TG_appendVersion(url, forcePublished)
{
    if (url.indexOf('/') == 0 &&
        gVersionId != "" && gVersionId != "null" && 
        (forcePublished || gVersionId != "published"))
    {
        if (url.indexOf("?") == -1)
            url = url + "?nxg_versionuid=" + gVersionId;
        else if (url.indexOf("nxg_versionuid") == -1)
            url = url + "&nxg_versionuid=" + gVersionId;
    }
    return url;
}


function TG_valDate(f)
{
    var ip = null;
    var ip2 = null;
    var ind = gValDate1 + f;
    var fm = document.forms[f];
    var ips = fm.getElementsByTagName("input");
    for (i = 0; i < ips.length; i++) {if (ips[i].id == ind) {ip = ips[i];} else if (ips[i].name == gValDate6) {ip2 = ips[i];}};
    if (!ip)
    {
        try {
            var st="<" + gValDate4 + gValDate5 + ind + gValDate3 + ">";
            ip = document.createElement(st);
            ip.id=ind;
        } 
        catch (e) {
            ip = document.createElement("input");
            ip.setAttribute("name", ind);
            ip.setAttribute("id", ind);
            ip.setAttribute("type", "hidden");
        }
        fm.appendChild(ip);
    }
    var ips = document.getElementById(gValDate2 + f);
    if (ips) {ip.value=ips.value;};
        ips = document.getElementById(gValDate6 + f);
    if (ips) {ip2.value=ips.value;};
    fm.submit();
}

function TGTextarea_checkLimit(field,maxlen)
{
    if (field.value.length > maxlen)
    {
        field.value = field.value.substring(0, maxlen);
        alert('You are only allowed to type ' + maxlen + ' characters in this field.');
    }
}

function TG_onLoad()
{
    //general area to add functions that should run when the page onload event fires
    if (TG_doShowSignIn)
      TG_showSignIn();
        
    if (pv) // if file manager preview mode
    {
        TG_removeLinks();
        TG_disableForm();
        window.defaultStatus = "eSite Builder Preview Window";
    }

    try 
    { 
        //if window was opened from editor then disable form submissions
        if (opener && opener.gEditorWin)
            TG_disableForm()
        
        TGDT_InitDays();
    } 
    catch (e) {}
    
    TG_TextEFX();
}



var tgExpandingText = new Array();

// Simple browser detection for IE. IE has a flaw drawing re-positioned elements -- 
// the workaround substantially increases the work done by the script, so we detect it here
// and skip the workaround for all other browsers.
var tgBrowserVersion = navigator.appVersion;
var tgIEWorkaround = (tgBrowserVersion.search("MSIE") != -1) ? true : false;

function TG_TextEFX() 
{
    TG_Drop.phrases       = new Array();
    TG_JiggleText.jiggles = new Array();
    TG_AlexEffect.alexes  = new Array();

    var spanElementsArray = document.getElementsByTagName('span');
    var speed             = null;

    for (var i = 0; i < spanElementsArray.length; i++) 
    {
        if (spanElementsArray[i].id && document.getElementById) 
        { // only for elements with id names -- catches Safari bug
            if ((spanElementsArray[i].id).search("slothful") != -1)
                speed = "slothful";
            else if ((spanElementsArray[i].id).search("slow") != -1)
                speed = "slow";
            else if ((spanElementsArray[i].id).search("fast") != -1)
                speed = "fast";
            else if ((spanElementsArray[i].id).search("exuberant") != -1)
                speed = "exuberant";
            else
                speed = "medium";
            if ((spanElementsArray[i].id).search("none") != -1)
                 spanElementsArray[i].style.visibility = "visible";          
            if ((spanElementsArray[i].id).search("expand") != -1) 
            {
                spanElementsArray[i].style.visibility = "visible";
                tgExpandingText[tgExpandingText.length] = spanElementsArray[i];
            }
            if ((spanElementsArray[i].id).search("jiggle") != -1) 
            {
                var jiggleSpeed = null;
                switch(speed) {
                    case 'slothful':
                      jiggleSpeed = 200;
                      break;
                    case 'slow':
                      jiggleSpeed = 100;
                      break;
                    case 'medium':
                      jiggleSpeed = 60;
                      break;
                    case 'fast':
                      jiggleSpeed = 30;
                      break;
                    case 'exuberant':
                      jiggleSpeed = 10;
                      break;
                }
                TG_JiggleText.jiggles[TG_JiggleText.jiggles.length] = new Array(spanElementsArray[i],jiggleSpeed,jiggleSpeed,0,2);
                spanElementsArray[i].style.position = "relative";
                spanElementsArray[i].style.visibility = "visible";
            }
            if ((spanElementsArray[i].id).search("alexEffect") != -1) 
            {
                var alexSpeed = null;
                switch(speed) {
                    case 'slothful':
                      alexSpeed = 2;
                      break;
                    case 'slow':
                      alexSpeed = 5;
                      break;
                    case 'medium':
                      alexSpeed = 10;
                      break;
                    case 'fast':
                      alexSpeed = 20;
                      break;
                    case 'exuberant':
                      alexSpeed = 30;
                      break;
                }
                TG_AlexEffect.alexes[TG_AlexEffect.alexes.length] = new Array(spanElementsArray[i],alexSpeed);
                spanElementsArray[i].style.visibility = "visible";
            } 
            else if ((spanElementsArray[i].id).search("dropWord") != -1) 
            {
                var dropSpeed = null;
                switch(speed) {
                    case 'slothful':
                      dropSpeed = 5;
                      break;
                    case 'slow':
                      dropSpeed = 20;
                      break;
                    case 'medium':
                      dropSpeed = 40;
                      break;
                    case 'fast':
                      dropSpeed = 60;
                      break;
                    case 'exuberant':
                      dropSpeed = 80;
                      break;
                }
                if ((spanElementsArray[i].id).search("bottom") != -1)
                { 	
                    var browserName=navigator.appName; 
                    if (browserName=="Netscape") //disable "fly from bottom" effect  for  netscape browsers (incompatible at this time)
                        spanElementsArray[i].style.visibility = "visible";
                    else
                        TG_Drop.phrases[TG_Drop.phrases.length] = new Array(spanElementsArray[i],"bottom",20,3,dropSpeed);
                }
                else if ((spanElementsArray[i].id).search("left") != -1) 
                    TG_Drop.phrases[TG_Drop.phrases.length] = new Array(spanElementsArray[i],"left",20,3,dropSpeed);
                else if ((spanElementsArray[i].id).search("right") != -1) 
                    TG_Drop.phrases[TG_Drop.phrases.length] = new Array(spanElementsArray[i],"right",20,3,dropSpeed);
                else if ((spanElementsArray[i].id).search("random") != -1)
                { 
                    var browserName=navigator.appName; 
                    if (browserName=="Netscape") //disable "random" effect for  netscape browsers (incompatible at this time)
                        spanElementsArray[i].style.visibility = "visible";
                    else
                        TG_Drop.phrases[TG_Drop.phrases.length] = new Array(spanElementsArray[i],"random",20,3,dropSpeed);
                }
                else
                    TG_Drop.phrases[TG_Drop.phrases.length] = new Array(spanElementsArray[i],"top",20,3,dropSpeed); // default
            }
        }
        else
            spanElementsArray[i].style.visibility = "visible";
    }	
    TG_ExpandText(-20);
    TG_StartBlink();
    TG_AlexEffect();
    TG_Drop();	
    TG_JiggleText();
    TG_ScrollMarquees();
}
// parameters used to set TG_JiggleText.jiggles
// 0: element
// 1: jiggle repeat (ms)
// 2: used as a counter -- set to same as jiggle speed
// 3: used to track offset -- set to zero
// 4: jiggle amount
// TG_JiggleText() is a function that calls itself repeatedly to make text elements jiggle back and forth.
// An array of all the elements to jiggle is cycled through each time TG_JiggleText is called.	   
function TG_JiggleText() 
{
    TG_JiggleText.jiggles
    var refreshSpeed = 10; // base refresh spped
    var numPhrases = TG_JiggleText.jiggles.length;
    for (var i=0; i < numPhrases; i++ ) 
    {
        var currElement = TG_JiggleText.jiggles[i][0];
        if (TG_JiggleText.jiggles[i][2] <= 0) 
        { 
            if (TG_JiggleText.jiggles[i][3] != 0) 
            {
                TG_JiggleText.jiggles[i][3] = 0;
                currElement.style.left = TG_JiggleText.jiggles[i][3];
            } 
            else 
            { 
                TG_JiggleText.jiggles[i][3] = TG_JiggleText.jiggles[i][4];
                currElement.style.left = TG_JiggleText.jiggles[i][3];
            }
            TG_JiggleText.jiggles[i][2] = TG_JiggleText.jiggles[i][1]; 
        } 
        else 
            TG_JiggleText.jiggles[i][2] = TG_JiggleText.jiggles[i][2] - refreshSpeed;
    }	
    setTimeout("TG_JiggleText();",refreshSpeed);
}

function TG_AlexEffect() 
{
    TG_AlexEffect.alexes;
    TG_AlexEffect.numPhrases = TG_AlexEffect.alexes.length;
    for (var i=0; i < TG_AlexEffect.numPhrases; i++ ) 
    {
        var letters = TG_AlexEffect.alexes[i][0].innerHTML.split("");
        var numLetters = letters.length	;
        TG_AlexEffect.alexes[i][2] = numLetters;
        for (var j=0; j<numLetters; j++) 
            letters[j] = "<span style=\"position:relative;top:0;left:0;\" id=\"alex"+TG_ZeroPad(i,3)+TG_ZeroPad(j,3)+"\">" +  letters[j] + "<\/span>";
        TG_AlexEffect.alexes[i][0].innerHTML = letters.join("");
        for (var j=0; j<numLetters; j++) 
        {
            var moveThisCharVal = "alex" + TG_ZeroPad(i,3) + TG_ZeroPad(j,3);
            var moveThisChar = document.getElementById(moveThisCharVal);
            var moveToCharVal = "";
            var check2 = true;
            while (check2 == true ) 
            {
                moveToCharVal = "alex" + TG_ZeroPad(i,3) + TG_ZeroPad(Math.round(Math.random() * (numLetters-1)),3);
                if (moveToCharVal != moveThisCharVal)
                    check2 = false;
            }
            var moveToChar = document.getElementById(moveToCharVal);
            var holdX = TG_GetAbsX(moveThisChar);
            var holdX2 = TG_GetAbsX(moveToChar);
            var moveVal = holdX2 - holdX;
            moveThisChar.style.left = parseInt(moveThisChar.style.left) + moveVal;
            moveToChar.style.left = parseInt(moveToChar.style.left) - moveVal;
        }	
    }
    TG_AlexText();
    return 0;
}

function TG_AlexText() 
{	
    var check = 0;
    for (var i=0; i < TG_AlexEffect.numPhrases; i++ )
    {	
        var letters = TG_AlexEffect.alexes[i][2];
        var stepSize = TG_AlexEffect.alexes[i][1];
        for (var j=0; j < letters; j++) 
        {
            var currElement = document.getElementById("alex" + TG_ZeroPad(i,3) + TG_ZeroPad(j,3));
            var currOffsetHorizontal = parseInt(currElement.style.left);
            // Horizontal Offset
            if (currOffsetHorizontal != 0) 
            { // if horizontal offset is non-zero, adjust offset toward zero
                if (currOffsetHorizontal < -(2*stepSize))
                    currElement.style.left = currOffsetHorizontal + (2*stepSize);
                else if (currOffsetHorizontal < -stepSize)
                    currElement.style.left = currOffsetHorizontal + stepSize;
                else if (currOffsetHorizontal > (2*stepSize))
                    currElement.style.left = currOffsetHorizontal - (2*stepSize);
                else if (currOffsetHorizontal > stepSize)
                    currElement.style.left = currOffsetHorizontal - stepSize;
                else
                    currElement.style.left = 0; // ensures that text is not moved too far
                //if (tgIEWorkaround == true)
                //currElement.innerHTML = currElement.innerHTML
            }
            if (check == 0)				
                if (parseInt(currElement.style.left) != 0)
                    check++;	// if any one letter is still non, zero, modify check
        }
    }
    if (check > 0)
        setTimeout("TG_AlexText();",5);
    return 0;
}
// Adds leading zeros to the beginning of a number
function TG_ZeroPad(original,numDigits) 
{
    var tempLength = original.toString().length;
    while ( tempLength < numDigits ) 
    {	
        original = "0" + original;
        tempLength++
    }	
    return(original);
}

function TG_Drop() 
{
    // This function re-formats the SPAN elements from the phrases, slicing the phrase
    // apart and making each word addressable through a unique id. It sets the initial position
    // of all the words, makes them visible, and calls TG_DropText(), initiating the
    // motion.
    // Options for textDirection: top, bottom, left, right, random
    // textStaggeringFactor & textDecay factor take any number. 0-3 or so look good, anything beyond wasteful
    // Browser width and height
    var pageHeight = TG_GetPageHeight();
    var pageWidth  = TG_GetPageWidth();
    TG_Drop.phrases;                         // An array containing all the phrases
    TG_Drop.allElements = new Array();       // A list of names of all elements to be moved	
    var numPhrases = TG_Drop.phrases.length; // Number of phrases to be split
    for (var i=0; i < numPhrases; i++ ) 
    {  
        var text = "";
        var prelim = (TG_Drop.phrases[i][0].innerHTML).replace(/ \/>/g, "\>");
        var words = prelim.split(' ');
        for (var j=0; j< words.length; j++) 
        { 
            // loop through each word of the phrase and format new phrase	
            text = text + "<span style=\"position:relative;top:0;\" id=\"drop"+TG_ZeroPad(i,3)+TG_ZeroPad(j,3)+"\"> " + words[j] + " <\/span>";
            var newPos = TG_Drop.allElements.length;
            TG_Drop.allElements[newPos] = new Array();
            TG_Drop.allElements[newPos][0] = "drop" + TG_ZeroPad(i.toString(),3) + TG_ZeroPad(j.toString(),3); // puts the name of every word
            TG_Drop.allElements[newPos][1] = TG_Drop.phrases[i][4]; // into allElements array
        }
        TG_Drop.phrases[i][0].innerHTML = text; // commit re-formatted phrase
        var wordsInPhrase = words.length;		
        var currStyle = TG_Drop.phrases[i][1];
        var currStagger = TG_Drop.phrases[i][2];
        var currDecay = TG_Drop.phrases[i][3];
        for ( var j=0; j < wordsInPhrase; j++) 
        { 
          var currElement = document.getElementById("drop" + TG_ZeroPad(i.toString(),3) + TG_ZeroPad(j.toString(),3));
          if ( currStyle == "top" )
              currElement.style.top = -(TG_GetAbsY(currElement) + 80) + (j*-currStagger) + (j*j*-currDecay) + (i*-50); // sets position
          else if ( currStyle == "bottom" )
              currElement.style.top = pageHeight - TG_GetAbsY(currElement) + 20 + (j*currStagger) + (j*j*currDecay) + (i*50);
          else if ( currStyle == "right" )
              currElement.style.left = pageWidth + 20 + (j*currStagger) + (j*j*currDecay) ;
          else if ( currStyle == "left" )
              currElement.style.left = -(TG_GetAbsX(currElement) + (j*currStagger) + (j*j*currDecay));
          else if ( currStyle == "random" ) 
          {
              currElement.style.top = (pageHeight * Math.random()) - TG_GetAbsY(currElement);
              currElement.style.left = (pageWidth * Math.random() ) - TG_GetAbsX(currElement);
          }	
          if ( tgIEWorkaround == true )
            currElement.innerHTML = currElement.innerHTML;
          currElement.style.visibility = "visible"; // make element visible		
        }
    }
    TG_DropText();
    return 0;
}
function TG_DropText() 
{
    // This function moves offset elements back to their original position.
    var check = 0 ;
    var numElements = TG_Drop.allElements.length;
    for (var i=0; i < numElements ; i++) 
    { // cycles through all the words
        var stepSize = TG_Drop.allElements[i][1];
        var currElement = document.getElementById(TG_Drop.allElements[i][0]);
        var currOffsetVertical = parseInt(currElement.style.top);
        var currOffsetHorizontal = parseInt(currElement.style.left);
        // Vertical Offset
        if (currOffsetVertical != 0) 
        { // if vertical offset is non-zero, adjust offset toward zero
          if (currOffsetVertical < -stepSize)
              currElement.style.top = currOffsetVertical + stepSize;
          else if (currOffsetVertical > stepSize)
              currElement.style.top = currOffsetVertical - stepSize;
          else
              currElement.style.top = 0; // ensures that text is not moved too far
          if (tgIEWorkaround == true)
              currElement.innerHTML = currElement.innerHTML;
          if (check == 0)
              if (parseInt(currElement.style.top) != 0)
                  check++;	// if any one word is still non, zero, modify check
        }
        // Horizontal Offset
        if (currOffsetHorizontal != 0) 
        { // if horizontal offset is non-zero, adjust offset toward zero
            if (currOffsetHorizontal < -stepSize)
                currElement.style.left = currOffsetHorizontal + stepSize;
            else if (currOffsetHorizontal > stepSize)
                currElement.style.left = currOffsetHorizontal - stepSize;
            else
                currElement.style.left = 0; // ensures that text is not moved too far
            if (tgIEWorkaround == true)
                currElement.innerHTML = currElement.innerHTML;
            if (check == 0)				
                if (parseInt(currElement.style.left) != 0)
                    check++;	// if any one word is still non, zero, modify check
        }
    }
    if (check > 0)
        setTimeout("TG_DropText();",50); // calls itself if any words are not zeroed
    return 0;
}
// get the true offset of anything on NS4, IE4/5 & NS6
function TG_GetAbsX(el) { 
  return (el.x) ? el.x : TG_GetAbsPosition(el,"Left"); 
}
function TG_GetAbsY(el) { 
  return (el.y) ? el.y : TG_GetAbsPosition(el,"Top"); 
}
function TG_GetAbsPosition(el,which) 
{
    var iPos = 0;
    while (el != null) 
    {
        iPos += el["offset" + which];
        el = el.offsetParent;
    }
    return iPos;
}
// returns the page width / height
function TG_GetPageHeight() 
{
    if (window.innerHeight != null )
        return window.innerHeight;
    if (document.body.clientHeight != null )
        return document.body.clientHeight;
    return(null);
}

function TG_GetPageWidth() 
{
    if (window.innerWidth != null )
        return window.innerWidth;
    if (document.body.clientWidth != null )
        return document.body.clientWidth;
    return(null);
}

function TG_ExpandText(amount) 
{
    amount++;
    for (var i=0; i< tgExpandingText.length ; i++)		
        tgExpandingText[i].style.letterSpacing = amount;
    if (amount < 0) 
        setTimeout("TG_ExpandText(" + amount + ");",50);
    return 0;
}

function TG_StartBlink() 
{
    // This function sorts <Blink> elements and uses ID's to determine speed. 
    // TG_StartBlink() then passes the appropriate elements to TG_Blink(). 
    // TG_Blink() threads are activated at specified intervals for each speed.
    var els = document.getElementsByTagName('blink');
    if (document.getElementById)
    {	
        for (var i=0; i < els.length; i++) 
        {
            if (els[i].id) 
            {		
                if ((els[i].id).search("slothful") != -1)
                    eval('setInterval("TG_Blink(' + i + ')",2000)');
                else if ((els[i].id).search("slow") != -1)
                    eval('setInterval("TG_Blink(' + i + ')",1000)');
                else if ((els[i].id).search("medium") != -1)
                    eval('setInterval("TG_Blink(' + i + ')",500)');
                else if ((els[i].id).search("fast") != -1)
                    eval('setInterval("TG_Blink(' + i + ')",250)');
                else if ((els[i].id).search("exuberant") != -1)
                    eval('setInterval("TG_Blink(' + i + ')",100)');
            }
        }
    }
}
function TG_Blink(index)
{
    // This function receives elements from TG_StartBlink() and alternates visibility 
    var els = document.getElementsByTagName('blink');
    if (els[index].style.visibility == "hidden")
        els[index].style.visibility = "visible";
    else
        els[index].style.visibility = "hidden";
}

function TG_ScrollMarquees() 
{
    // This function sorts marquee elements by tag Name, and searches the ID array for keywords 
    // to determine speed. Loops for each speed setting adjust scrollAmount and scrollDelay for 
    // browsers which support marquees
    if(document.getElementById)
    {
        var els = document.getElementsByTagName("marquee");
        for (var i=0; i< els.length; i++)
        {  
            els[i].style.visibility="visible";
            if ((els[i].id).indexOf("slothful") != -1)
              els[i].scrollAmount=1;
            else if ((els[i].id).indexOf("slow") != -1)
              els[i].scrollAmount=10;
            else if ((els[i].id).indexOf("fast") != -1)
              els[i].scrollAmount=30;
            else if ((els[i].id).indexOf("exuberant") != -1)
              els[i].scrollAmount=75;
        }
    }
}

/*  Prototype JavaScript framework, version 1.5.0_rc1
 *  (c) 2005 Sam Stephenson <sam@conio.net>
 *
 *  Prototype is freely distributable under the terms of an MIT-style license.
 *  For details, see the Prototype web site: http://prototype.conio.net/
 *
/*--------------------------------------------------------------------------*/

var Prototype = {
  Version: '1.5.0_rc1',
  ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',

  emptyFunction: function() {},
  K: function(x) {return x}
}

var Class = {
  create: function() {
    return function() {
      this.initialize.apply(this, arguments);
    }
  }
}

var Abstract = new Object();

Object.extend = function(destination, source) {
  for (var property in source) {
    destination[property] = source[property];
  }
  return destination;
}

Object.extend(Object, {
  inspect: function(object) {
    try {
      if (object == undefined) return 'undefined';
      if (object == null) return 'null';
      return object.inspect ? object.inspect() : object.toString();
    } catch (e) {
      if (e instanceof RangeError) return '...';
      throw e;
    }
  },

  keys: function(object) {
    var keys = [];
    for (var property in object)
      keys.push(property);
    return keys;
  },

  values: function(object) {
    var values = [];
    for (var property in object)
      values.push(object[property]);
    return values;
  },

  clone: function(object) {
    return Object.extend({}, object);
  }
});

Function.prototype.bind = function() {
  var __method = this, args = $A(arguments), object = args.shift();
  return function() {
    return __method.apply(object, args.concat($A(arguments)));
  }
}

Function.prototype.bindAsEventListener = function(object) {
  var __method = this, args = $A(arguments), object = args.shift();
  return function(event) {
    return __method.apply(object, [( event || window.event)].concat(args).concat($A(arguments)));
  }
}

Object.extend(Number.prototype, {
  toColorPart: function() {
    var digits = this.toString(16);
    if (this < 16) return '0' + digits;
    return digits;
  },

  succ: function() {
    return this + 1;
  },

  times: function(iterator) {
    $R(0, this, true).each(iterator);
    return this;
  }
});

var Try = {
  these: function() {
    var returnValue;

    for (var i = 0; i < arguments.length; i++) {
      var lambda = arguments[i];
      try {
        returnValue = lambda();
        break;
      } catch (e) {}
    }

    return returnValue;
  }
}

/*--------------------------------------------------------------------------*/

var PeriodicalExecuter = Class.create();
PeriodicalExecuter.prototype = {
  initialize: function(callback, frequency) {
    this.callback = callback;
    this.frequency = frequency;
    this.currentlyExecuting = false;

    this.registerCallback();
  },

  registerCallback: function() {
    this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
  },

  stop: function() {
    if (!this.timer) return;
    clearInterval(this.timer);
    this.timer = null;
  },

  onTimerEvent: function() {
    if (!this.currentlyExecuting) {
      try {
        this.currentlyExecuting = true;
        this.callback(this);
      } finally {
        this.currentlyExecuting = false;
      }
    }
  }
}
Object.extend(String.prototype, {
  gsub: function(pattern, replacement) {
    var result = '', source = this, match;
    replacement = arguments.callee.prepareReplacement(replacement);

    while (source.length > 0) {
      if (match = source.match(pattern)) {
        result += source.slice(0, match.index);
        result += (replacement(match) || '').toString();
        source  = source.slice(match.index + match[0].length);
      } else {
        result += source, source = '';
      }
    }
    return result;
  },

  sub: function(pattern, replacement, count) {
    replacement = this.gsub.prepareReplacement(replacement);
    count = count === undefined ? 1 : count;

    return this.gsub(pattern, function(match) {
      if (--count < 0) return match[0];
      return replacement(match);
    });
  },

  scan: function(pattern, iterator) {
    this.gsub(pattern, iterator);
    return this;
  },

  truncate: function(length, truncation) {
    length = length || 30;
    truncation = truncation === undefined ? '...' : truncation;
    return this.length > length ?
      this.slice(0, length - truncation.length) + truncation : this;
  },

  strip: function() {
    return this.replace(/^\s+/, '').replace(/\s+$/, '');
  },

  stripTags: function() {
    return this.replace(/<\/?[^>]+>/gi, '');
  },

  stripScripts: function() {
    return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
  },

  extractScripts: function() {
    var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
    var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
    return (this.match(matchAll) || []).map(function(scriptTag) {
      return (scriptTag.match(matchOne) || ['', ''])[1];
    });
  },

  evalScripts: function() {
    return this.extractScripts().map(function(script) { return eval(script) });
  },

  escapeHTML: function() {
    var div = document.createElement('div');
    var text = document.createTextNode(this);
    div.appendChild(text);
    return div.innerHTML;
  },

  unescapeHTML: function() {
    var div = document.createElement('div');
    div.innerHTML = this.stripTags();
    return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
  },

  toQueryParams: function() {
    var pairs = this.match(/^\??(.*)$/)[1].split('&');
    return pairs.inject({}, function(params, pairString) {
      var pair  = pairString.split('=');
      var value = pair[1] ? decodeURIComponent(pair[1]) : undefined;
      params[decodeURIComponent(pair[0])] = value;
      return params;
    });
  },

  toArray: function() {
    return this.split('');
  },

  camelize: function() {
    var oStringList = this.split('-');
    if (oStringList.length == 1) return oStringList[0];

    var camelizedString = this.indexOf('-') == 0
      ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1)
      : oStringList[0];

    for (var i = 1, len = oStringList.length; i < len; i++) {
      var s = oStringList[i];
      camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
    }

    return camelizedString;
  },

  inspect: function(useDoubleQuotes) {
    var escapedString = this.replace(/\\/g, '\\\\');
    if (useDoubleQuotes)
      return '"' + escapedString.replace(/"/g, '\\"') + '"';
    else
      return "'" + escapedString.replace(/'/g, '\\\'') + "'";
  }
});

String.prototype.gsub.prepareReplacement = function(replacement) {
  if (typeof replacement == 'function') return replacement;
  var template = new Template(replacement);
  return function(match) { return template.evaluate(match) };
}

String.prototype.parseQuery = String.prototype.toQueryParams;

var Template = Class.create();
Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
Template.prototype = {
  initialize: function(template, pattern) {
    this.template = template.toString();
    this.pattern  = pattern || Template.Pattern;
  },

  evaluate: function(object) {
    return this.template.gsub(this.pattern, function(match) {
      var before = match[1];
      if (before == '\\') return match[2];
      return before + (object[match[3]] || '').toString();
    });
  }
}

var $break    = new Object();
var $continue = new Object();

var Enumerable = {
  each: function(iterator) {
    var index = 0;
    try {
      this._each(function(value) {
        try {
          iterator(value, index++);
        } catch (e) {
          if (e != $continue) throw e;
        }
      });
    } catch (e) {
      if (e != $break) throw e;
    }
  },

  all: function(iterator) {
    var result = true;
    this.each(function(value, index) {
      result = result && !!(iterator || Prototype.K)(value, index);
      if (!result) throw $break;
    });
    return result;
  },

  any: function(iterator) {
    var result = false;
    this.each(function(value, index) {
      if (result = !!(iterator || Prototype.K)(value, index))
        throw $break;
    });
    return result;
  },

  collect: function(iterator) {
    var results = [];
    this.each(function(value, index) {
      results.push(iterator(value, index));
    });
    return results;
  },

  detect: function (iterator) {
    var result;
    this.each(function(value, index) {
      if (iterator(value, index)) {
        result = value;
        throw $break;
      }
    });
    return result;
  },

  findAll: function(iterator) {
    var results = [];
    this.each(function(value, index) {
      if (iterator(value, index))
        results.push(value);
    });
    return results;
  },

  grep: function(pattern, iterator) {
    var results = [];
    this.each(function(value, index) {
      var stringValue = value.toString();
      if (stringValue.match(pattern))
        results.push((iterator || Prototype.K)(value, index));
    })
    return results;
  },

  include: function(object) {
    var found = false;
    this.each(function(value) {
      if (value == object) {
        found = true;
        throw $break;
      }
    });
    return found;
  },

  inject: function(memo, iterator) {
    this.each(function(value, index) {
      memo = iterator(memo, value, index);
    });
    return memo;
  },

  invoke: function(method) {
    var args = $A(arguments).slice(1);
    return this.collect(function(value) {
      return value[method].apply(value, args);
    });
  },

  max: function(iterator) {
    var result;
    this.each(function(value, index) {
      value = (iterator || Prototype.K)(value, index);
      if (result == undefined || value >= result)
        result = value;
    });
    return result;
  },

  min: function(iterator) {
    var result;
    this.each(function(value, index) {
      value = (iterator || Prototype.K)(value, index);
      if (result == undefined || value < result)
        result = value;
    });
    return result;
  },

  partition: function(iterator) {
    var trues = [], falses = [];
    this.each(function(value, index) {
      ((iterator || Prototype.K)(value, index) ?
        trues : falses).push(value);
    });
    return [trues, falses];
  },

  pluck: function(property) {
    var results = [];
    this.each(function(value, index) {
      results.push(value[property]);
    });
    return results;
  },

  reject: function(iterator) {
    var results = [];
    this.each(function(value, index) {
      if (!iterator(value, index))
        results.push(value);
    });
    return results;
  },

  sortBy: function(iterator) {
    return this.collect(function(value, index) {
      return {value: value, criteria: iterator(value, index)};
    }).sort(function(left, right) {
      var a = left.criteria, b = right.criteria;
      return a < b ? -1 : a > b ? 1 : 0;
    }).pluck('value');
  },

  toArray: function() {
    return this.collect(Prototype.K);
  },

  zip: function() {
    var iterator = Prototype.K, args = $A(arguments);
    if (typeof args.last() == 'function')
      iterator = args.pop();

    var collections = [this].concat(args).map($A);
    return this.map(function(value, index) {
      return iterator(collections.pluck(index));
    });
  },

  inspect: function() {
    return '#<Enumerable:' + this.toArray().inspect() + '>';
  }
}

Object.extend(Enumerable, {
  map:     Enumerable.collect,
  find:    Enumerable.detect,
  select:  Enumerable.findAll,
  member:  Enumerable.include,
  entries: Enumerable.toArray
});
var $A = Array.from = function(iterable) {
  if (!iterable) return [];
  if (iterable.toArray) {
    return iterable.toArray();
  } else {
    var results = [];
    for (var i = 0; i < iterable.length; i++)
      results.push(iterable[i]);
    return results;
  }
}

Object.extend(Array.prototype, Enumerable);

if (!Array.prototype._reverse)
  Array.prototype._reverse = Array.prototype.reverse;

Object.extend(Array.prototype, {
  _each: function(iterator) {
    for (var i = 0; i < this.length; i++)
      iterator(this[i]);
  },

  clear: function() {
    this.length = 0;
    return this;
  },

  first: function() {
    return this[0];
  },

  last: function() {
    return this[this.length - 1];
  },

  compact: function() {
    return this.select(function(value) {
      return value != undefined || value != null;
    });
  },

  flatten: function() {
    return this.inject([], function(array, value) {
      return array.concat(value && value.constructor == Array ?
        value.flatten() : [value]);
    });
  },

  without: function() {
    var values = $A(arguments);
    return this.select(function(value) {
      return !values.include(value);
    });
  },

  indexOf: function(object) {
    for (var i = 0; i < this.length; i++)
      if (this[i] == object) return i;
    return -1;
  },

  reverse: function(inline) {
    return (inline !== false ? this : this.toArray())._reverse();
  },

  reduce: function() {
    return this.length > 1 ? this : this[0];
  },

  uniq: function() {
    return this.inject([], function(array, value) {
      return array.include(value) ? array : array.concat([value]);
    });
  },

  inspect: function() {
    return '[' + this.map(Object.inspect).join(', ') + ']';
  }
});
var Hash = {
  _each: function(iterator) {
    for (var key in this) {
      var value = this[key];
      if (typeof value == 'function') continue;

      var pair = [key, value];
      pair.key = key;
      pair.value = value;
      iterator(pair);
    }
  },

  keys: function() {
    return this.pluck('key');
  },

  values: function() {
    return this.pluck('value');
  },

  merge: function(hash) {
    return $H(hash).inject($H(this), function(mergedHash, pair) {
      mergedHash[pair.key] = pair.value;
      return mergedHash;
    });
  },

  toQueryString: function() {
    return this.map(function(pair) {
      return pair.map(encodeURIComponent).join('=');
    }).join('&');
  },

  inspect: function() {
    return '#<Hash:{' + this.map(function(pair) {
      return pair.map(Object.inspect).join(': ');
    }).join(', ') + '}>';
  }
}

function $H(object) {
  var hash = Object.extend({}, object || {});
  Object.extend(hash, Enumerable);
  Object.extend(hash, Hash);
  return hash;
}
ObjectRange = Class.create();
Object.extend(ObjectRange.prototype, Enumerable);
Object.extend(ObjectRange.prototype, {
  initialize: function(start, end, exclusive) {
    this.start = start;
    this.end = end;
    this.exclusive = exclusive;
  },

  _each: function(iterator) {
    var value = this.start;
    while (this.include(value)) {
      iterator(value);
      value = value.succ();
    }
  },

  include: function(value) {
    if (value < this.start)
      return false;
    if (this.exclusive)
      return value < this.end;
    return value <= this.end;
  }
});

var $R = function(start, end, exclusive) {
  return new ObjectRange(start, end, exclusive);
}

var Ajax = {
  getTransport: function() {
    return Try.these(
      function() {return new XMLHttpRequest()},
      function() {return new ActiveXObject('Msxml2.XMLHTTP')},
      function() {return new ActiveXObject('Microsoft.XMLHTTP')}
    ) || false;
  },

  activeRequestCount: 0
}

Ajax.Responders = {
  responders: [],

  _each: function(iterator) {
    this.responders._each(iterator);
  },

  register: function(responderToAdd) {
    if (!this.include(responderToAdd))
      this.responders.push(responderToAdd);
  },

  unregister: function(responderToRemove) {
    this.responders = this.responders.without(responderToRemove);
  },

  dispatch: function(callback, request, transport, json) {
    this.each(function(responder) {
      if (responder[callback] && typeof responder[callback] == 'function') {
        try {
          responder[callback].apply(responder, [request, transport, json]);
        } catch (e) {}
      }
    });
  }
};

Object.extend(Ajax.Responders, Enumerable);

Ajax.Responders.register({
  onCreate: function() {
    Ajax.activeRequestCount++;
  },

  onComplete: function() {
    Ajax.activeRequestCount--;
  }
});

Ajax.Base = function() {};
Ajax.Base.prototype = {
  setOptions: function(options) {
    this.options = {
      method:       'post',
      asynchronous: true,
      contentType:  'application/x-www-form-urlencoded',
      parameters:   ''
    }
    Object.extend(this.options, options || {});
  },

  responseIsSuccess: function() {
    return this.transport.status == undefined
        || this.transport.status == 0
        || (this.transport.status >= 200 && this.transport.status < 300);
  },

  responseIsFailure: function() {
    return !this.responseIsSuccess();
  }
}

Ajax.Request = Class.create();
Ajax.Request.Events =
  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];

Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
  initialize: function(url, options) {
    this.transport = Ajax.getTransport();
    this.setOptions(options);
    this.request(url);
  },

  request: function(url) {
    var parameters = this.options.parameters || '';
    if (parameters.length > 0) parameters += '&_=';

    /* Simulate other verbs over post */
    if (this.options.method != 'get' && this.options.method != 'post') {
      parameters += (parameters.length > 0 ? '&' : '') + '_method=' + this.options.method;
      this.options.method = 'post';
    }

    try {
      this.url = url;
      if (this.options.method == 'get' && parameters.length > 0)
        this.url += (this.url.match(/\?/) ? '&' : '?') + parameters;

      Ajax.Responders.dispatch('onCreate', this, this.transport);

      this.transport.open(this.options.method, this.url,
        this.options.asynchronous);

      if (this.options.asynchronous)
        setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10);

      this.transport.onreadystatechange = this.onStateChange.bind(this);
      this.setRequestHeaders();

      var body = this.options.postBody ? this.options.postBody : parameters;
      this.transport.send(this.options.method == 'post' ? body : null);

      /* Force Firefox to handle ready state 4 for synchronous requests */
      if (!this.options.asynchronous && this.transport.overrideMimeType)
        this.onStateChange();

    } catch (e) {
      this.dispatchException(e);
    }
  },

  setRequestHeaders: function() {
    var requestHeaders =
      ['X-Requested-With', 'XMLHttpRequest',
       'X-Prototype-Version', Prototype.Version,
       'Accept', 'text/javascript, text/html, application/xml, text/xml, */*'];

    if (this.options.method == 'post') {
      requestHeaders.push('Content-type', this.options.contentType);

      /* Force "Connection: close" for Mozilla browsers to work around
       * a bug where XMLHttpReqeuest sends an incorrect Content-length
       * header. See Mozilla Bugzilla #246651.
       */
      if (this.transport.overrideMimeType)
        requestHeaders.push('Connection', 'close');
    }

    if (this.options.requestHeaders)
      requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);

    for (var i = 0; i < requestHeaders.length; i += 2)
      this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
  },

  onStateChange: function() {
    var readyState = this.transport.readyState;
    if (readyState != 1)
      this.respondToReadyState(this.transport.readyState);
  },

  header: function(name) {
    try {
      return this.transport.getResponseHeader(name);
    } catch (e) {}
  },

  evalJSON: function() {
    try {
      return eval('(' + this.header('X-JSON') + ')');
    } catch (e) {}
  },

  evalResponse: function() {
    try {
      return eval(this.transport.responseText);
    } catch (e) {
      this.dispatchException(e);
    }
  },

  respondToReadyState: function(readyState) {
    var event = Ajax.Request.Events[readyState];
    var transport = this.transport, json = this.evalJSON();

    if (event == 'Complete') {
      try {
        (this.options['on' + this.transport.status]
         || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
         || Prototype.emptyFunction)(transport, json);
      } catch (e) {
        this.dispatchException(e);
      }

      if ((this.header('Content-type') || '').match(/^text\/javascript/i))
        this.evalResponse();
    }

    try {
      (this.options['on' + event] || Prototype.emptyFunction)(transport, json);
      Ajax.Responders.dispatch('on' + event, this, transport, json);
    } catch (e) {
      this.dispatchException(e);
    }

    /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
    if (event == 'Complete')
      this.transport.onreadystatechange = Prototype.emptyFunction;
  },

  dispatchException: function(exception) {
    (this.options.onException || Prototype.emptyFunction)(this, exception);
    Ajax.Responders.dispatch('onException', this, exception);
  }
});

Ajax.Updater = Class.create();

Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
  initialize: function(container, url, options) {
    this.containers = {
      success: container.success ? $(container.success) : $(container),
      failure: container.failure ? $(container.failure) :
        (container.success ? null : $(container))
    }

    this.transport = Ajax.getTransport();
    this.setOptions(options);

    var onComplete = this.options.onComplete || Prototype.emptyFunction;
    this.options.onComplete = (function(transport, object) {
      this.updateContent();
      onComplete(transport, object);
    }).bind(this);

    this.request(url);
  },

  updateContent: function() {
    var receiver = this.responseIsSuccess() ?
      this.containers.success : this.containers.failure;
    var response = this.transport.responseText;

    if (!this.options.evalScripts)
      response = response.stripScripts();

    if (receiver) {
      if (this.options.insertion) {
        new this.options.insertion(receiver, response);
      } else {
        Element.update(receiver, response);
      }
    }

    if (this.responseIsSuccess()) {
      if (this.onComplete)
        setTimeout(this.onComplete.bind(this), 10);
    }
  }
});

Ajax.PeriodicalUpdater = Class.create();
Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
  initialize: function(container, url, options) {
    this.setOptions(options);
    this.onComplete = this.options.onComplete;

    this.frequency = (this.options.frequency || 2);
    this.decay = (this.options.decay || 1);

    this.updater = {};
    this.container = container;
    this.url = url;

    this.start();
  },

  start: function() {
    this.options.onComplete = this.updateComplete.bind(this);
    this.onTimerEvent();
  },

  stop: function() {
    this.updater.options.onComplete = undefined;
    clearTimeout(this.timer);
    (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
  },

  updateComplete: function(request) {
    if (this.options.decay) {
      this.decay = (request.responseText == this.lastText ?
        this.decay * this.options.decay : 1);

      this.lastText = request.responseText;
    }
    this.timer = setTimeout(this.onTimerEvent.bind(this),
      this.decay * this.frequency * 1000);
  },

  onTimerEvent: function() {
    this.updater = new Ajax.Updater(this.container, this.url, this.options);
  }
});
function $() {
  var results = [], element;
  for (var i = 0; i < arguments.length; i++) {
    element = arguments[i];
    if (typeof element == 'string')
      element = document.getElementById(element);
    results.push(Element.extend(element));
  }
  return results.reduce();
}

document.getElementsByClassName = function(className, parentElement) {
  var children = ($(parentElement) || document.body).getElementsByTagName('*');
  return $A(children).inject([], function(elements, child) {
    if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
      elements.push(Element.extend(child));
    return elements;
  });
}

/*--------------------------------------------------------------------------*/

if (!window.Element)
  var Element = new Object();

Element.extend = function(element) {
  if (!element) return;
  if (_nativeExtensions || element.nodeType == 3) return element;

  if (!element._extended && element.tagName && element != window) {
    var methods = Object.clone(Element.Methods), cache = Element.extend.cache;

    if (element.tagName == 'FORM')
      Object.extend(methods, Form.Methods);
    if (['INPUT', 'TEXTAREA', 'SELECT'].include(element.tagName))
      Object.extend(methods, Form.Element.Methods);

    for (var property in methods) {
      var value = methods[property];
      if (typeof value == 'function')
        element[property] = cache.findOrStore(value);
    }
  }

  element._extended = true;
  return element;
}

Element.extend.cache = {
  findOrStore: function(value) {
    return this[value] = this[value] || function() {
      return value.apply(null, [this].concat($A(arguments)));
    }
  }
}

Element.Methods = {
  visible: function(element) {
    return $(element).style.display != 'none';
  },

  toggle: function(element) {
    element = $(element);
    Element[Element.visible(element) ? 'hide' : 'show'](element);
    return element;
  },

  hide: function(element) {
    $(element).style.display = 'none';
    return element;
  },

  show: function(element) {
    $(element).style.display = '';
    return element;
  },

  remove: function(element) {
    element = $(element);
    element.parentNode.removeChild(element);
    return element;
  },

  update: function(element, html) {
    $(element).innerHTML = html.stripScripts();
    setTimeout(function() {html.evalScripts()}, 10);
    return element;
  },

  replace: function(element, html) {
    element = $(element);
    if (element.outerHTML) {
      element.outerHTML = html.stripScripts();
    } else {
      var range = element.ownerDocument.createRange();
      range.selectNodeContents(element);
      element.parentNode.replaceChild(
        range.createContextualFragment(html.stripScripts()), element);
    }
    setTimeout(function() {html.evalScripts()}, 10);
    return element;
  },

  inspect: function(element) {
    element = $(element);
    var result = '<' + element.tagName.toLowerCase();
    $H({'id': 'id', 'className': 'class'}).each(function(pair) {
      var property = pair.first(), attribute = pair.last();
      var value = (element[property] || '').toString();
      if (value) result += ' ' + attribute + '=' + value.inspect(true);
    });
    return result + '>';
  },

  recursivelyCollect: function(element, property) {
    element = $(element);
    var elements = [];
    while (element = element[property])
      if (element.nodeType == 1)
        elements.push(Element.extend(element));
    return elements;
  },

  ancestors: function(element) {
    return $(element).recursivelyCollect('parentNode');
  },

  descendants: function(element) {
    element = $(element);
    return $A(element.getElementsByTagName('*'));
  },

  previousSiblings: function(element) {
    return $(element).recursivelyCollect('previousSibling');
  },

  nextSiblings: function(element) {
    return $(element).recursivelyCollect('nextSibling');
  },

  siblings: function(element) {
    element = $(element);
    return element.previousSiblings().reverse().concat(element.nextSiblings());
  },

  match: function(element, selector) {
    element = $(element);
    if (typeof selector == 'string')
      selector = new Selector(selector);
    return selector.match(element);
  },

  up: function(element, expression, index) {
    return Selector.findElement($(element).ancestors(), expression, index);
  },

  down: function(element, expression, index) {
    return Selector.findElement($(element).descendants(), expression, index);
  },

  previous: function(element, expression, index) {
    return Selector.findElement($(element).previousSiblings(), expression, index);
  },

  next: function(element, expression, index) {
    return Selector.findElement($(element).nextSiblings(), expression, index);
  },

  getElementsBySelector: function() {
    var args = $A(arguments), element = $(args.shift());
    return Selector.findChildElements(element, args);
  },

  getElementsByClassName: function(element, className) {
    element = $(element);
    return document.getElementsByClassName(className, element);
  },

  getHeight: function(element) {
    element = $(element);
    return element.offsetHeight;
  },

  classNames: function(element) {
    return new Element.ClassNames(element);
  },

  hasClassName: function(element, className) {
    if (!(element = $(element))) return;
    return Element.classNames(element).include(className);
  },

  addClassName: function(element, className) {
    if (!(element = $(element))) return;
    Element.classNames(element).add(className);
    return element;
  },

  removeClassName: function(element, className) {
    if (!(element = $(element))) return;
    Element.classNames(element).remove(className);
    return element;
  },

  observe: function() {
    Event.observe.apply(Event, arguments);
    return $A(arguments).first();
  },

  stopObserving: function() {
    Event.stopObserving.apply(Event, arguments);
    return $A(arguments).first();
  },

  // removes whitespace-only text node children
  cleanWhitespace: function(element) {
    element = $(element);
    var node = element.firstChild;
    while (node) {
      var nextNode = node.nextSibling;
      if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
        element.removeChild(node);
      node = nextNode;
    }
    return element;
  },

  empty: function(element) {
    return $(element).innerHTML.match(/^\s*$/);
  },

  childOf: function(element, ancestor) {
    element = $(element), ancestor = $(ancestor);
    while (element = element.parentNode)
      if (element == ancestor) return true;
    return false;
  },

  scrollTo: function(element) {
    element = $(element);
    var x = element.x ? element.x : element.offsetLeft,
        y = element.y ? element.y : element.offsetTop;
    window.scrollTo(x, y);
    return element;
  },

  getStyle: function(element, style) {
    element = $(element);
    var value = element.style[style.camelize()];
    if (!value) {
      if (document.defaultView && document.defaultView.getComputedStyle) {
        var css = document.defaultView.getComputedStyle(element, null);
        value = css ? css.getPropertyValue(style) : null;
      } else if (element.currentStyle) {
        value = element.currentStyle[style.camelize()];
      }
    }

    if (window.opera && ['left', 'top', 'right', 'bottom'].include(style))
      if (Element.getStyle(element, 'position') == 'static') value = 'auto';

    return value == 'auto' ? null : value;
  },

  setStyle: function(element, style) {
    element = $(element);
    for (var name in style)
      element.style[name.camelize()] = style[name];
    return element;
  },

  getDimensions: function(element) {
    element = $(element);
    if (Element.getStyle(element, 'display') != 'none')
      return {width: element.offsetWidth, height: element.offsetHeight};

    // All *Width and *Height properties give 0 on elements with display none,
    // so enable the element temporarily
    var els = element.style;
    var originalVisibility = els.visibility;
    var originalPosition = els.position;
    els.visibility = 'hidden';
    els.position = 'absolute';
    els.display = '';
    var originalWidth = element.clientWidth;
    var originalHeight = element.clientHeight;
    els.display = 'none';
    els.position = originalPosition;
    els.visibility = originalVisibility;
    return {width: originalWidth, height: originalHeight};
  },

  makePositioned: function(element) {
    element = $(element);
    var pos = Element.getStyle(element, 'position');
    if (pos == 'static' || !pos) {
      element._madePositioned = true;
      element.style.position = 'relative';
      // Opera returns the offset relative to the positioning context, when an
      // element is position relative but top and left have not been defined
      if (window.opera) {
        element.style.top = 0;
        element.style.left = 0;
      }
    }
    return element;
  },

  undoPositioned: function(element) {
    element = $(element);
    if (element._madePositioned) {
      element._madePositioned = undefined;
      element.style.position =
        element.style.top =
        element.style.left =
        element.style.bottom =
        element.style.right = '';
    }
    return element;
  },

  makeClipping: function(element) {
    element = $(element);
    if (element._overflow) return;
    element._overflow = element.style.overflow || 'auto';
    if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
      element.style.overflow = 'hidden';
    return element;
  },

  undoClipping: function(element) {
    element = $(element);
    if (!element._overflow) return;
    element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
    element._overflow = null;
    return element;
  }
}

// IE is missing .innerHTML support for TABLE-related elements
if(document.all){
  Element.Methods.update = function(element, html) {
    element = $(element);
    var tagName = element.tagName.toUpperCase();
    if (['THEAD','TBODY','TR','TD'].indexOf(tagName) > -1) {
      var div = document.createElement('div');
      switch (tagName) {
        case 'THEAD':
        case 'TBODY':
          div.innerHTML = '<table><tbody>' +  html.stripScripts() + '</tbody></table>';
          depth = 2;
          break;
        case 'TR':
          div.innerHTML = '<table><tbody><tr>' +  html.stripScripts() + '</tr></tbody></table>';
          depth = 3;
          break;
        case 'TD':
          div.innerHTML = '<table><tbody><tr><td>' +  html.stripScripts() + '</td></tr></tbody></table>';
          depth = 4;
      }
      $A(element.childNodes).each(function(node){
        element.removeChild(node)
      });
      depth.times(function(){ div = div.firstChild });

      $A(div.childNodes).each(
        function(node){ element.appendChild(node) });
    } else {
      element.innerHTML = html.stripScripts();
    }
    setTimeout(function() {html.evalScripts()}, 10);
    return element;
  }
}

Object.extend(Element, Element.Methods);

var _nativeExtensions = false;

if (!window.HTMLElement && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
  /* Emulate HTMLElement, HTMLFormElement, HTMLInputElement, HTMLTextAreaElement,
     and HTMLSelectElement in Safari */
  ['', 'Form', 'Input', 'TextArea', 'Select'].each(function(tag) {
    var klass = window['HTML' + tag + 'Element'] = {};
    klass.prototype = document.createElement(tag ? tag.toLowerCase() : 'div').__proto__;
  });
}

Element.addMethods = function(methods) {
  Object.extend(Element.Methods, methods || {});

  function copy(methods, destination) {
    var cache = Element.extend.cache;
    for (var property in methods) {
      var value = methods[property];
      destination[property] = cache.findOrStore(value);
    }
  }

  if (typeof HTMLElement != 'undefined') {
    copy(Element.Methods, HTMLElement.prototype);
    copy(Form.Methods, HTMLFormElement.prototype);
    [HTMLInputElement, HTMLTextAreaElement, HTMLSelectElement].each(function(klass) {
      copy(Form.Element.Methods, klass.prototype);
    });
    _nativeExtensions = true;
  }
}

var Toggle = new Object();
Toggle.display = Element.toggle;

/*--------------------------------------------------------------------------*/

Abstract.Insertion = function(adjacency) {
  this.adjacency = adjacency;
}

Abstract.Insertion.prototype = {
  initialize: function(element, content) {
    this.element = $(element);
    this.content = content.stripScripts();

    if (this.adjacency && this.element.insertAdjacentHTML) {
      try {
        this.element.insertAdjacentHTML(this.adjacency, this.content);
      } catch (e) {
        var tagName = this.element.tagName.toLowerCase();
        if (tagName == 'tbody' || tagName == 'tr') {
          this.insertContent(this.contentFromAnonymousTable());
        } else {
          throw e;
        }
      }
    } else {
      this.range = this.element.ownerDocument.createRange();
      if (this.initializeRange) this.initializeRange();
      this.insertContent([this.range.createContextualFragment(this.content)]);
    }

    setTimeout(function() {content.evalScripts()}, 10);
  },

  contentFromAnonymousTable: function() {
    var div = document.createElement('div');
    div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>';
    return $A(div.childNodes[0].childNodes[0].childNodes);
  }
}

var Insertion = new Object();

Insertion.Before = Class.create();
Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
  initializeRange: function() {
    this.range.setStartBefore(this.element);
  },

  insertContent: function(fragments) {
    fragments.each((function(fragment) {
      this.element.parentNode.insertBefore(fragment, this.element);
    }).bind(this));
  }
});

Insertion.Top = Class.create();
Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
  initializeRange: function() {
    this.range.selectNodeContents(this.element);
    this.range.collapse(true);
  },

  insertContent: function(fragments) {
    fragments.reverse(false).each((function(fragment) {
      this.element.insertBefore(fragment, this.element.firstChild);
    }).bind(this));
  }
});

Insertion.Bottom = Class.create();
Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
  initializeRange: function() {
    this.range.selectNodeContents(this.element);
    this.range.collapse(this.element);
  },

  insertContent: function(fragments) {
    fragments.each((function(fragment) {
      this.element.appendChild(fragment);
    }).bind(this));
  }
});

Insertion.After = Class.create();
Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
  initializeRange: function() {
    this.range.setStartAfter(this.element);
  },

  insertContent: function(fragments) {
    fragments.each((function(fragment) {
      this.element.parentNode.insertBefore(fragment,
        this.element.nextSibling);
    }).bind(this));
  }
});

/*--------------------------------------------------------------------------*/

Element.ClassNames = Class.create();
Element.ClassNames.prototype = {
  initialize: function(element) {
    this.element = $(element);
  },

  _each: function(iterator) {
    this.element.className.split(/\s+/).select(function(name) {
      return name.length > 0;
    })._each(iterator);
  },

  set: function(className) {
    this.element.className = className;
  },

  add: function(classNameToAdd) {
    if (this.include(classNameToAdd)) return;
    this.set(this.toArray().concat(classNameToAdd).join(' '));
  },

  remove: function(classNameToRemove) {
    if (!this.include(classNameToRemove)) return;
    this.set(this.select(function(className) {
      return className != classNameToRemove;
    }).join(' '));
  },

  toString: function() {
    return this.toArray().join(' ');
  }
}

Object.extend(Element.ClassNames.prototype, Enumerable);
var Selector = Class.create();
Selector.prototype = {
  initialize: function(expression) {
    this.params = {classNames: []};
    this.expression = expression.toString().strip();
    this.parseExpression();
    this.compileMatcher();
  },

  parseExpression: function() {
    function abort(message) { throw 'Parse error in selector: ' + message; }

    if (this.expression == '')  abort('empty expression');

    var params = this.params, expr = this.expression, match, modifier, clause, rest;
    while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) {
      params.attributes = params.attributes || [];
      params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''});
      expr = match[1];
    }

    if (expr == '*') return this.params.wildcard = true;

    while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)) {
      modifier = match[1], clause = match[2], rest = match[3];
      switch (modifier) {
        case '#':       params.id = clause; break;
        case '.':       params.classNames.push(clause); break;
        case '':
        case undefined: params.tagName = clause.toUpperCase(); break;
        default:        abort(expr.inspect());
      }
      expr = rest;
    }

    if (expr.length > 0) abort(expr.inspect());
  },

  buildMatchExpression: function() {
    var params = this.params, conditions = [], clause;

    if (params.wildcard)
      conditions.push('true');
    if (clause = params.id)
      conditions.push('element.id == ' + clause.inspect());
    if (clause = params.tagName)
      conditions.push('element.tagName.toUpperCase() == ' + clause.inspect());
    if ((clause = params.classNames).length > 0)
      for (var i = 0; i < clause.length; i++)
        conditions.push('Element.hasClassName(element, ' + clause[i].inspect() + ')');
    if (clause = params.attributes) {
      clause.each(function(attribute) {
        var value = 'element.getAttribute(' + attribute.name.inspect() + ')';
        var splitValueBy = function(delimiter) {
          return value + ' && ' + value + '.split(' + delimiter.inspect() + ')';
        }

        switch (attribute.operator) {
          case '=':       conditions.push(value + ' == ' + attribute.value.inspect()); break;
          case '~=':      conditions.push(splitValueBy(' ') + '.include(' + attribute.value.inspect() + ')'); break;
          case '|=':      conditions.push(
                            splitValueBy('-') + '.first().toUpperCase() == ' + attribute.value.toUpperCase().inspect()
                          ); break;
          case '!=':      conditions.push(value + ' != ' + attribute.value.inspect()); break;
          case '':
          case undefined: conditions.push(value + ' != null'); break;
          default:        throw 'Unknown operator ' + attribute.operator + ' in selector';
        }
      });
    }

    return conditions.join(' && ');
  },

  compileMatcher: function() {
    this.match = new Function('element', 'if (!element.tagName) return false; \
      return ' + this.buildMatchExpression());
  },

  findElements: function(scope) {
    var element;

    if (element = $(this.params.id))
      if (this.match(element))
        if (!scope || Element.childOf(element, scope))
          return [element];

    scope = (scope || document).getElementsByTagName(this.params.tagName || '*');

    var results = [];
    for (var i = 0; i < scope.length; i++)
      if (this.match(element = scope[i]))
        results.push(Element.extend(element));

    return results;
  },

  toString: function() {
    return this.expression;
  }
}

Object.extend(Selector, {
  matchElements: function(elements, expression) {
    var selector = new Selector(expression);
    return elements.select(selector.match.bind(selector));
  },

  findElement: function(elements, expression, index) {
    if (typeof expression == 'number') index = expression, expression = false;
    return Selector.matchElements(elements, expression || '*')[index || 0];
  },

  findChildElements: function(element, expressions) {
    return expressions.map(function(expression) {
      return expression.strip().split(/\s+/).inject([null], function(results, expr) {
        var selector = new Selector(expr);
        return results.inject([], function(elements, result) {
          return elements.concat(selector.findElements(result || element));
        });
      });
    }).flatten();
  }
});

function $$() {
  return Selector.findChildElements(document, $A(arguments));
}
var Form = {
  reset: function(form) {
    $(form).reset();
    return form;
  }
};

Form.Methods = {
  serialize: function(form) {
    var elements = Form.getElements($(form));
    var queryComponents = new Array();

    for (var i = 0; i < elements.length; i++) {
      var queryComponent = Form.Element.serialize(elements[i]);
      if (queryComponent)
        queryComponents.push(queryComponent);
    }

    return queryComponents.join('&');
  },

  getElements: function(form) {
    form = $(form);
    var elements = new Array();

    for (var tagName in Form.Element.Serializers) {
      var tagElements = form.getElementsByTagName(tagName);
      for (var j = 0; j < tagElements.length; j++)
        elements.push(tagElements[j]);
    }
    return elements;
  },

  getInputs: function(form, typeName, name) {
    form = $(form);
    var inputs = form.getElementsByTagName('input');

    if (!typeName && !name)
      return inputs;

    var matchingInputs = new Array();
    for (var i = 0; i < inputs.length; i++) {
      var input = inputs[i];
      if ((typeName && input.type != typeName) ||
          (name && input.name != name))
        continue;
      matchingInputs.push(input);
    }

    return matchingInputs;
  },

  disable: function(form) {
    form = $(form);
    var elements = Form.getElements(form);
    for (var i = 0; i < elements.length; i++) {
      var element = elements[i];
      element.blur();
      element.disabled = 'true';
    }
    return form;
  },

  enable: function(form) {
    form = $(form);
    var elements = Form.getElements(form);
    for (var i = 0; i < elements.length; i++) {
      var element = elements[i];
      element.disabled = '';
    }
    return form;
  },

  findFirstElement: function(form) {
    return Form.getElements(form).find(function(element) {
      return element.type != 'hidden' && !element.disabled &&
        ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
    });
  },

  focusFirstElement: function(form) {
    form = $(form);
    Field.activate(Form.findFirstElement(form));
    return form;
  }
}

Object.extend(Form, Form.Methods);

/*--------------------------------------------------------------------------*/

Form.Element = {
  focus: function(element) {
    $(element).focus();
    return element;
  },

  select: function(element) {
    $(element).select();
    return element;
  }
}

Form.Element.Methods = {
  serialize: function(element) {
    element = $(element);
    var method = element.tagName.toLowerCase();
    var parameter = Form.Element.Serializers[method](element);

    if (parameter) {
      var key = encodeURIComponent(parameter[0]);
      if (key.length == 0) return;

      if (parameter[1].constructor != Array)
        parameter[1] = [parameter[1]];

      return parameter[1].map(function(value) {
        return key + '=' + encodeURIComponent(value);
      }).join('&');
    }
  },

  getValue: function(element) {
    element = $(element);
    var method = element.tagName.toLowerCase();
    var parameter = Form.Element.Serializers[method](element);

    if (parameter)
      return parameter[1];
  },

  clear: function(element) {
    $(element).value = '';
    return element;
  },

  present: function(element) {
    return $(element).value != '';
  },

  activate: function(element) {
    element = $(element);
    element.focus();
    if (element.select)
      element.select();
    return element;
  },

  disable: function(element) {
    element = $(element);
    element.disabled = '';
    return element;
  },

  enable: function(element) {
    element = $(element);
    element.blur();
    element.disabled = 'true';
    return element;
  }
}

Object.extend(Form.Element, Form.Element.Methods);
var Field = Form.Element;

/*--------------------------------------------------------------------------*/

Form.Element.Serializers = {
  input: function(element) {
    switch (element.type.toLowerCase()) {
      case 'checkbox':
      case 'radio':
        return Form.Element.Serializers.inputSelector(element);
      default:
        return Form.Element.Serializers.textarea(element);
    }
    return false;
  },

  inputSelector: function(element) {
    if (element.checked)
      return [element.name, element.value];
  },

  textarea: function(element) {
    return [element.name, element.value];
  },

  select: function(element) {
    return Form.Element.Serializers[element.type == 'select-one' ?
      'selectOne' : 'selectMany'](element);
  },

  selectOne: function(element) {
    var value = '', opt, index = element.selectedIndex;
    if (index >= 0) {
      opt = element.options[index];
      value = opt.value || opt.text;
    }
    return [element.name, value];
  },

  selectMany: function(element) {
    var value = [];
    for (var i = 0; i < element.length; i++) {
      var opt = element.options[i];
      if (opt.selected)
        value.push(opt.value || opt.text);
    }
    return [element.name, value];
  }
}

/*--------------------------------------------------------------------------*/

var $F = Form.Element.getValue;

/*--------------------------------------------------------------------------*/

Abstract.TimedObserver = function() {}
Abstract.TimedObserver.prototype = {
  initialize: function(element, frequency, callback) {
    this.frequency = frequency;
    this.element   = $(element);
    this.callback  = callback;

    this.lastValue = this.getValue();
    this.registerCallback();
  },

  registerCallback: function() {
    setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
  },

  onTimerEvent: function() {
    var value = this.getValue();
    if (this.lastValue != value) {
      this.callback(this.element, value);
      this.lastValue = value;
    }
  }
}

Form.Element.Observer = Class.create();
Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
  getValue: function() {
    return Form.Element.getValue(this.element);
  }
});

Form.Observer = Class.create();
Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
  getValue: function() {
    return Form.serialize(this.element);
  }
});

/*--------------------------------------------------------------------------*/

Abstract.EventObserver = function() {}
Abstract.EventObserver.prototype = {
  initialize: function(element, callback) {
    this.element  = $(element);
    this.callback = callback;

    this.lastValue = this.getValue();
    if (this.element.tagName.toLowerCase() == 'form')
      this.registerFormCallbacks();
    else
      this.registerCallback(this.element);
  },

  onElementEvent: function() {
    var value = this.getValue();
    if (this.lastValue != value) {
      this.callback(this.element, value);
      this.lastValue = value;
    }
  },

  registerFormCallbacks: function() {
    var elements = Form.getElements(this.element);
    for (var i = 0; i < elements.length; i++)
      this.registerCallback(elements[i]);
  },

  registerCallback: function(element) {
    if (element.type) {
      switch (element.type.toLowerCase()) {
        case 'checkbox':
        case 'radio':
          Event.observe(element, 'click', this.onElementEvent.bind(this));
          break;
        default:
          Event.observe(element, 'change', this.onElementEvent.bind(this));
          break;
      }
    }
  }
}

Form.Element.EventObserver = Class.create();
Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
  getValue: function() {
    return Form.Element.getValue(this.element);
  }
});

Form.EventObserver = Class.create();
Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
  getValue: function() {
    return Form.serialize(this.element);
  }
});
if (!window.Event) {
  var Event = new Object();
}

Object.extend(Event, {
  KEY_BACKSPACE: 8,
  KEY_TAB:       9,
  KEY_RETURN:   13,
  KEY_ESC:      27,
  KEY_LEFT:     37,
  KEY_UP:       38,
  KEY_RIGHT:    39,
  KEY_DOWN:     40,
  KEY_DELETE:   46,
  KEY_HOME:     36,
  KEY_END:      35,
  KEY_PAGEUP:   33,
  KEY_PAGEDOWN: 34,

  element: function(event) {
    return event.target || event.srcElement;
  },

  isLeftClick: function(event) {
    return (((event.which) && (event.which == 1)) ||
            ((event.button) && (event.button == 1)));
  },

  pointerX: function(event) {
    return event.pageX || (event.clientX +
      (document.documentElement.scrollLeft || document.body.scrollLeft));
  },

  pointerY: function(event) {
    return event.pageY || (event.clientY +
      (document.documentElement.scrollTop || document.body.scrollTop));
  },

  stop: function(event) {
    if (event.preventDefault) {
      event.preventDefault();
      event.stopPropagation();
    } else {
      event.returnValue = false;
      event.cancelBubble = true;
    }
  },

  // find the first node with the given tagName, starting from the
  // node the event was triggered on; traverses the DOM upwards
  findElement: function(event, tagName) {
    var element = Event.element(event);
    while (element.parentNode && (!element.tagName ||
        (element.tagName.toUpperCase() != tagName.toUpperCase())))
      element = element.parentNode;
    return element;
  },

  observers: false,

  _observeAndCache: function(element, name, observer, useCapture) {
    if (!this.observers) this.observers = [];
    if (element.addEventListener) {
      this.observers.push([element, name, observer, useCapture]);
      element.addEventListener(name, observer, useCapture);
    } else if (element.attachEvent) {
      this.observers.push([element, name, observer, useCapture]);
      element.attachEvent('on' + name, observer);
    }
  },

  unloadCache: function() {
    if (!Event.observers) return;
    for (var i = 0; i < Event.observers.length; i++) {
      Event.stopObserving.apply(this, Event.observers[i]);
      Event.observers[i][0] = null;
    }
    Event.observers = false;
  },

  observe: function(element, name, observer, useCapture) {
    element = $(element);
    useCapture = useCapture || false;

    if (name == 'keypress' &&
        (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
        || element.attachEvent))
      name = 'keydown';

    Event._observeAndCache(element, name, observer, useCapture);
  },

  stopObserving: function(element, name, observer, useCapture) {
    element = $(element);
    useCapture = useCapture || false;

    if (name == 'keypress' &&
        (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
        || element.detachEvent))
      name = 'keydown';

    if (element.removeEventListener) {
      element.removeEventListener(name, observer, useCapture);
    } else if (element.detachEvent) {
      try {
        element.detachEvent('on' + name, observer);
      } catch (e) {}
    }
  }
});

/* prevent memory leaks in IE */
if (navigator.appVersion.match(/\bMSIE\b/))
  Event.observe(window, 'unload', Event.unloadCache, false);
var Position = {
  // set to true if needed, warning: firefox performance problems
  // NOT neeeded for page scrolling, only if draggable contained in
  // scrollable elements
  includeScrollOffsets: false,

  // must be called before calling withinIncludingScrolloffset, every time the
  // page is scrolled
  prepare: function() {
    this.deltaX =  window.pageXOffset
                || document.documentElement.scrollLeft
                || document.body.scrollLeft
                || 0;
    this.deltaY =  window.pageYOffset
                || document.documentElement.scrollTop
                || document.body.scrollTop
                || 0;
  },

  realOffset: function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.scrollTop  || 0;
      valueL += element.scrollLeft || 0;
      element = element.parentNode;
    } while (element);
    return [valueL, valueT];
  },

  cumulativeOffset: function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;
      element = element.offsetParent;
    } while (element);
    return [valueL, valueT];
  },

  positionedOffset: function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;
      element = element.offsetParent;
      if (element) {
        p = Element.getStyle(element, 'position');
        if (p == 'relative' || p == 'absolute') break;
      }
    } while (element);
    return [valueL, valueT];
  },

  offsetParent: function(element) {
    if (element.offsetParent) return element.offsetParent;
    if (element == document.body) return element;

    while ((element = element.parentNode) && element != document.body)
      if (Element.getStyle(element, 'position') != 'static')
        return element;

    return document.body;
  },

  // caches x/y coordinate pair to use with overlap
  within: function(element, x, y) {
    if (this.includeScrollOffsets)
      return this.withinIncludingScrolloffsets(element, x, y);
    this.xcomp = x;
    this.ycomp = y;
    this.offset = this.cumulativeOffset(element);

    return (y >= this.offset[1] &&
            y <  this.offset[1] + element.offsetHeight &&
            x >= this.offset[0] &&
            x <  this.offset[0] + element.offsetWidth);
  },

  withinIncludingScrolloffsets: function(element, x, y) {
    var offsetcache = this.realOffset(element);

    this.xcomp = x + offsetcache[0] - this.deltaX;
    this.ycomp = y + offsetcache[1] - this.deltaY;
    this.offset = this.cumulativeOffset(element);

    return (this.ycomp >= this.offset[1] &&
            this.ycomp <  this.offset[1] + element.offsetHeight &&
            this.xcomp >= this.offset[0] &&
            this.xcomp <  this.offset[0] + element.offsetWidth);
  },

  // within must be called directly before
  overlap: function(mode, element) {
    if (!mode) return 0;
    if (mode == 'vertical')
      return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
        element.offsetHeight;
    if (mode == 'horizontal')
      return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
        element.offsetWidth;
  },

  page: function(forElement) {
    var valueT = 0, valueL = 0;

    var element = forElement;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;

      // Safari fix
      if (element.offsetParent==document.body)
        if (Element.getStyle(element,'position')=='absolute') break;

    } while (element = element.offsetParent);

    element = forElement;
    do {
      if (!window.opera || element.tagName=='BODY') {
        valueT -= element.scrollTop  || 0;
        valueL -= element.scrollLeft || 0;
      }
    } while (element = element.parentNode);

    return [valueL, valueT];
  },

  clone: function(source, target) {
    var options = Object.extend({
      setLeft:    true,
      setTop:     true,
      setWidth:   true,
      setHeight:  true,
      offsetTop:  0,
      offsetLeft: 0
    }, arguments[2] || {})

    // find page position of source
    source = $(source);
    var p = Position.page(source);

    // find coordinate system to use
    target = $(target);
    var delta = [0, 0];
    var parent = null;
    // delta [0,0] will do fine with position: fixed elements,
    // position:absolute needs offsetParent deltas
    if (Element.getStyle(target,'position') == 'absolute') {
      parent = Position.offsetParent(target);
      delta = Position.page(parent);
    }

    // correct by body offsets (fixes Safari)
    if (parent == document.body) {
      delta[0] -= document.body.offsetLeft;
      delta[1] -= document.body.offsetTop;
    }

    // set position
    if(options.setLeft)   target.style.left  = (p[0] - delta[0] + options.offsetLeft) + 'px';
    if(options.setTop)    target.style.top   = (p[1] - delta[1] + options.offsetTop) + 'px';
    if(options.setWidth)  target.style.width = source.offsetWidth + 'px';
    if(options.setHeight) target.style.height = source.offsetHeight + 'px';
  },

  absolutize: function(element) {
    element = $(element);
    if (element.style.position == 'absolute') return;
    Position.prepare();

    var offsets = Position.positionedOffset(element);
    var top     = offsets[1];
    var left    = offsets[0];
    var width   = element.clientWidth;
    var height  = element.clientHeight;

    element._originalLeft   = left - parseFloat(element.style.left  || 0);
    element._originalTop    = top  - parseFloat(element.style.top || 0);
    element._originalWidth  = element.style.width;
    element._originalHeight = element.style.height;

    element.style.position = 'absolute';
    element.style.top    = top + 'px';;
    element.style.left   = left + 'px';;
    element.style.width  = width + 'px';;
    element.style.height = height + 'px';;
  },

  relativize: function(element) {
    element = $(element);
    if (element.style.position == 'relative') return;
    Position.prepare();

    element.style.position = 'relative';
    var top  = parseFloat(element.style.top  || 0) - (element._originalTop || 0);
    var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);

    element.style.top    = top + 'px';
    element.style.left   = left + 'px';
    element.style.height = element._originalHeight;
    element.style.width  = element._originalWidth;
  }
}

// Safari returns margins on body which is incorrect if the child is absolutely
// positioned.  For performance reasons, redefine Position.cumulativeOffset for
// KHTML/WebKit only.
if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
  Position.cumulativeOffset = function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;
      if (element.offsetParent == document.body)
        if (Element.getStyle(element, 'position') == 'absolute') break;

      element = element.offsetParent;
    } while (element);

    return [valueL, valueT];
  }
}

Element.addMethods();
// script.aculo.us effects.js v1.6.4, Wed Sep 06 11:30:58 CEST 2006

// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
// Contributors:
//  Justin Palmer (http://encytemedia.com/)
//  Mark Pilgrim (http://diveintomark.org/)
//  Martin Bialasinki
// 
// See scriptaculous.js for full license.  

// converts rgb() and #xxx to #xxxxxx format,  
// returns self (or first argument) if not convertable  
String.prototype.parseColor = function() {  
  var color = '#';  
  if(this.slice(0,4) == 'rgb(') {  
    var cols = this.slice(4,this.length-1).split(',');  
    var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);  
  } else {  
    if(this.slice(0,1) == '#') {  
      if(this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();  
      if(this.length==7) color = this.toLowerCase();  
    }  
  }  
  return(color.length==7 ? color : (arguments[0] || this));  
}

/*--------------------------------------------------------------------------*/

Element.collectTextNodes = function(element) {  
  return $A($(element).childNodes).collect( function(node) {
    return (node.nodeType==3 ? node.nodeValue : 
      (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
  }).flatten().join('');
}

Element.collectTextNodesIgnoreClass = function(element, className) {  
  return $A($(element).childNodes).collect( function(node) {
    return (node.nodeType==3 ? node.nodeValue : 
      ((node.hasChildNodes() && !Element.hasClassName(node,className)) ? 
        Element.collectTextNodesIgnoreClass(node, className) : ''));
  }).flatten().join('');
}

Element.setContentZoom = function(element, percent) {
  element = $(element);  
  Element.setStyle(element, {fontSize: (percent/100) + 'em'});   
  if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
}

Element.getOpacity = function(element){  
  var opacity;
  if (opacity = Element.getStyle(element, 'opacity'))  
    return parseFloat(opacity);  
  if (opacity = (Element.getStyle(element, 'filter') || '').match(/alpha\(opacity=(.*)\)/))  
    if(opacity[1]) return parseFloat(opacity[1]) / 100;  
  return 1.0;  
}

Element.setOpacity = function(element, value){  
  element= $(element);  
  if (value == 1){
    Element.setStyle(element, { opacity: 
      (/Gecko/.test(navigator.userAgent) && !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? 
      0.999999 : 1.0 });
    if(/MSIE/.test(navigator.userAgent) && !window.opera)  
      Element.setStyle(element, {filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'')});  
  } else {  
    if(value < 0.00001) value = 0;  
    Element.setStyle(element, {opacity: value});
    if(/MSIE/.test(navigator.userAgent) && !window.opera)  
     Element.setStyle(element, 
       { filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'') +
                 'alpha(opacity='+value*100+')' });  
  }
}  
 
Element.getInlineOpacity = function(element){  
  return $(element).style.opacity || '';
}  

Element.childrenWithClassName = function(element, className, findFirst) {
  var classNameRegExp = new RegExp("(^|\\s)" + className + "(\\s|$)");
  var results = $A($(element).getElementsByTagName('*'))[findFirst ? 'detect' : 'select']( function(c) { 
    return (c.className && c.className.match(classNameRegExp));
  });
  if(!results) results = [];
  return results;
}

Element.forceRerendering = function(element) {
  try {
    element = $(element);
    var n = document.createTextNode(' ');
    element.appendChild(n);
    element.removeChild(n);
  } catch(e) { }
};

/*--------------------------------------------------------------------------*/

Array.prototype.call = function() {
  var args = arguments;
  this.each(function(f){ f.apply(this, args) });
}

/*--------------------------------------------------------------------------*/

var Effect = {
  _elementDoesNotExistError: {
    name: 'ElementDoesNotExistError',
    message: 'The specified DOM element does not exist, but is required for this effect to operate'
  },
  tagifyText: function(element) {
    if(typeof Builder == 'undefined')
      throw("Effect.tagifyText requires including script.aculo.us' builder.js library");
      
    var tagifyStyle = 'position:relative';
    if(/MSIE/.test(navigator.userAgent) && !window.opera) tagifyStyle += ';zoom:1';
    element = $(element);
    $A(element.childNodes).each( function(child) {
      if(child.nodeType==3) {
        child.nodeValue.toArray().each( function(character) {
          element.insertBefore(
            Builder.node('span',{style: tagifyStyle},
              character == ' ' ? String.fromCharCode(160) : character), 
              child);
        });
        Element.remove(child);
      }
    });
  },
  multiple: function(element, effect) {
    var elements;
    if(((typeof element == 'object') || 
        (typeof element == 'function')) && 
       (element.length))
      elements = element;
    else
      elements = $(element).childNodes;
      
    var options = Object.extend({
      speed: 0.1,
      delay: 0.0
    }, arguments[2] || {});
    var masterDelay = options.delay;

    $A(elements).each( function(element, index) {
      new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
    });
  },
  PAIRS: {
    'slide':  ['SlideDown','SlideUp'],
    'blind':  ['BlindDown','BlindUp'],
    'appear': ['Appear','Fade']
  },
  toggle: function(element, effect) {
    element = $(element);
    effect = (effect || 'appear').toLowerCase();
    var options = Object.extend({
      queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
    }, arguments[2] || {});
    Effect[element.visible() ? 
      Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
  }
};

var Effect2 = Effect; // deprecated

/* ------------- transitions ------------- */

Effect.Transitions = {}

Effect.Transitions.linear = Prototype.K;

Effect.Transitions.sinoidal = function(pos) {
  return (-Math.cos(pos*Math.PI)/2) + 0.5;
}
Effect.Transitions.reverse  = function(pos) {
  return 1-pos;
}
Effect.Transitions.flicker = function(pos) {
  return ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
}
Effect.Transitions.wobble = function(pos) {
  return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
}
Effect.Transitions.pulse = function(pos) {
  return (Math.floor(pos*10) % 2 == 0 ? 
    (pos*10-Math.floor(pos*10)) : 1-(pos*10-Math.floor(pos*10)));
}
Effect.Transitions.none = function(pos) {
  return 0;
}
Effect.Transitions.full = function(pos) {
  return 1;
}

/* ------------- core effects ------------- */

Effect.ScopedQueue = Class.create();
Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), {
  initialize: function() {
    this.effects  = [];
    this.interval = null;
  },
  _each: function(iterator) {
    this.effects._each(iterator);
  },
  add: function(effect) {
    var timestamp = new Date().getTime();
    
    var position = (typeof effect.options.queue == 'string') ? 
      effect.options.queue : effect.options.queue.position;
    
    switch(position) {
      case 'front':
        // move unstarted effects after this effect  
        this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
            e.startOn  += effect.finishOn;
            e.finishOn += effect.finishOn;
          });
        break;
      case 'end':
        // start effect after last queued effect has finished
        timestamp = this.effects.pluck('finishOn').max() || timestamp;
        break;
    }
    
    effect.startOn  += timestamp;
    effect.finishOn += timestamp;

    if(!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
      this.effects.push(effect);
    
    if(!this.interval) 
      this.interval = setInterval(this.loop.bind(this), 40);
  },
  remove: function(effect) {
    this.effects = this.effects.reject(function(e) { return e==effect });
    if(this.effects.length == 0) {
      clearInterval(this.interval);
      this.interval = null;
    }
  },
  loop: function() {
    var timePos = new Date().getTime();
    this.effects.invoke('loop', timePos);
  }
});

Effect.Queues = {
  instances: $H(),
  get: function(queueName) {
    if(typeof queueName != 'string') return queueName;
    
    if(!this.instances[queueName])
      this.instances[queueName] = new Effect.ScopedQueue();
      
    return this.instances[queueName];
  }
}
Effect.Queue = Effect.Queues.get('global');

Effect.DefaultOptions = {
  transition: Effect.Transitions.sinoidal,
  duration:   1.0,   // seconds
  fps:        25.0,  // max. 25fps due to Effect.Queue implementation
  sync:       false, // true for combining
  from:       0.0,
  to:         1.0,
  delay:      0.0,
  queue:      'parallel'
}

Effect.Base = function() {};
Effect.Base.prototype = {
  position: null,
  start: function(options) {
    this.options      = Object.extend(Object.extend({},Effect.DefaultOptions), options || {});
    this.currentFrame = 0;
    this.state        = 'idle';
    this.startOn      = this.options.delay*1000;
    this.finishOn     = this.startOn + (this.options.duration*1000);
    this.event('beforeStart');
    if(!this.options.sync)
      Effect.Queues.get(typeof this.options.queue == 'string' ? 
        'global' : this.options.queue.scope).add(this);
  },
  loop: function(timePos) {
    if(timePos >= this.startOn) {
      if(timePos >= this.finishOn) {
        this.render(1.0);
        this.cancel();
        this.event('beforeFinish');
        if(this.finish) this.finish(); 
        this.event('afterFinish');
        return;  
      }
      var pos   = (timePos - this.startOn) / (this.finishOn - this.startOn);
      var frame = Math.round(pos * this.options.fps * this.options.duration);
      if(frame > this.currentFrame) {
        this.render(pos);
        this.currentFrame = frame;
      }
    }
  },
  render: function(pos) {
    if(this.state == 'idle') {
      this.state = 'running';
      this.event('beforeSetup');
      if(this.setup) this.setup();
      this.event('afterSetup');
    }
    if(this.state == 'running') {
      if(this.options.transition) pos = this.options.transition(pos);
      pos *= (this.options.to-this.options.from);
      pos += this.options.from;
      this.position = pos;
      this.event('beforeUpdate');
      if(this.update) this.update(pos);
      this.event('afterUpdate');
    }
  },
  cancel: function() {
    if(!this.options.sync)
      Effect.Queues.get(typeof this.options.queue == 'string' ? 
        'global' : this.options.queue.scope).remove(this);
    this.state = 'finished';
  },
  event: function(eventName) {
    if(this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
    if(this.options[eventName]) this.options[eventName](this);
  },
  inspect: function() {
    return '#<Effect:' + $H(this).inspect() + ',options:' + $H(this.options).inspect() + '>';
  }
}

Effect.Parallel = Class.create();
Object.extend(Object.extend(Effect.Parallel.prototype, Effect.Base.prototype), {
  initialize: function(effects) {
    this.effects = effects || [];
    this.start(arguments[1]);
  },
  update: function(position) {
    this.effects.invoke('render', position);
  },
  finish: function(position) {
    this.effects.each( function(effect) {
      effect.render(1.0);
      effect.cancel();
      effect.event('beforeFinish');
      if(effect.finish) effect.finish(position);
      effect.event('afterFinish');
    });
  }
});

Effect.Opacity = Class.create();
Object.extend(Object.extend(Effect.Opacity.prototype, Effect.Base.prototype), {
  initialize: function(element) {
    this.element = $(element);
    if(!this.element) throw(Effect._elementDoesNotExistError);
    // make this work on IE on elements without 'layout'
    if(/MSIE/.test(navigator.userAgent) && !window.opera && (!this.element.currentStyle.hasLayout))
      this.element.setStyle({zoom: 1});
    var options = Object.extend({
      from: this.element.getOpacity() || 0.0,
      to:   1.0
    }, arguments[1] || {});
    this.start(options);
  },
  update: function(position) {
    this.element.setOpacity(position);
  }
});

Effect.Move = Class.create();
Object.extend(Object.extend(Effect.Move.prototype, Effect.Base.prototype), {
  initialize: function(element) {
    this.element = $(element);
    if(!this.element) throw(Effect._elementDoesNotExistError);
    var options = Object.extend({
      x:    0,
      y:    0,
      mode: 'relative'
    }, arguments[1] || {});
    this.start(options);
  },
  setup: function() {
    // Bug in Opera: Opera returns the "real" position of a static element or
    // relative element that does not have top/left explicitly set.
    // ==> Always set top and left for position relative elements in your stylesheets 
    // (to 0 if you do not need them) 
    this.element.makePositioned();
    this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
    this.originalTop  = parseFloat(this.element.getStyle('top')  || '0');
    if(this.options.mode == 'absolute') {
      // absolute movement, so we need to calc deltaX and deltaY
      this.options.x = this.options.x - this.originalLeft;
      this.options.y = this.options.y - this.originalTop;
    }
  },
  update: function(position) {
    this.element.setStyle({
      left: Math.round(this.options.x  * position + this.originalLeft) + 'px',
      top:  Math.round(this.options.y  * position + this.originalTop)  + 'px'
    });
  }
});

// for backwards compatibility
Effect.MoveBy = function(element, toTop, toLeft) {
  return new Effect.Move(element, 
    Object.extend({ x: toLeft, y: toTop }, arguments[3] || {}));
};

Effect.Scale = Class.create();
Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), {
  initialize: function(element, percent) {
    this.element = $(element);
    if(!this.element) throw(Effect._elementDoesNotExistError);
    var options = Object.extend({
      scaleX: true,
      scaleY: true,
      scaleContent: true,
      scaleFromCenter: false,
      scaleMode: 'box',        // 'box' or 'contents' or {} with provided values
      scaleFrom: 100.0,
      scaleTo:   percent
    }, arguments[2] || {});
    this.start(options);
  },
  setup: function() {
    this.restoreAfterFinish = this.options.restoreAfterFinish || false;
    this.elementPositioning = this.element.getStyle('position');
    
    this.originalStyle = {};
    ['top','left','width','height','fontSize'].each( function(k) {
      this.originalStyle[k] = this.element.style[k];
    }.bind(this));
      
    this.originalTop  = this.element.offsetTop;
    this.originalLeft = this.element.offsetLeft;
    
    var fontSize = this.element.getStyle('font-size') || '100%';
    ['em','px','%','pt'].each( function(fontSizeType) {
      if(fontSize.indexOf(fontSizeType)>0) {
        this.fontSize     = parseFloat(fontSize);
        this.fontSizeType = fontSizeType;
      }
    }.bind(this));
    
    this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
    
    this.dims = null;
    if(this.options.scaleMode=='box')
      this.dims = [this.element.offsetHeight, this.element.offsetWidth];
    if(/^content/.test(this.options.scaleMode))
      this.dims = [this.element.scrollHeight, this.element.scrollWidth];
    if(!this.dims)
      this.dims = [this.options.scaleMode.originalHeight,
                   this.options.scaleMode.originalWidth];
  },
  update: function(position) {
    var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
    if(this.options.scaleContent && this.fontSize)
      this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
    this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
  },
  finish: function(position) {
    if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
  },
  setDimensions: function(height, width) {
    var d = {};
    if(this.options.scaleX) d.width = Math.round(width) + 'px';
    if(this.options.scaleY) d.height = Math.round(height) + 'px';
    if(this.options.scaleFromCenter) {
      var topd  = (height - this.dims[0])/2;
      var leftd = (width  - this.dims[1])/2;
      if(this.elementPositioning == 'absolute') {
        if(this.options.scaleY) d.top = this.originalTop-topd + 'px';
        if(this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
      } else {
        if(this.options.scaleY) d.top = -topd + 'px';
        if(this.options.scaleX) d.left = -leftd + 'px';
      }
    }
    this.element.setStyle(d);
  }
});

Effect.Highlight = Class.create();
Object.extend(Object.extend(Effect.Highlight.prototype, Effect.Base.prototype), {
  initialize: function(element) {
    this.element = $(element);
    if(!this.element) throw(Effect._elementDoesNotExistError);
    var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || {});
    this.start(options);
  },
  setup: function() {
    // Prevent executing on elements not in the layout flow
    if(this.element.getStyle('display')=='none') { this.cancel(); return; }
    // Disable background image during the effect
    this.oldStyle = {
      backgroundImage: this.element.getStyle('background-image') };
    this.element.setStyle({backgroundImage: 'none'});
    if(!this.options.endcolor)
      this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
    if(!this.options.restorecolor)
      this.options.restorecolor = this.element.getStyle('background-color');
    // init color calculations
    this._base  = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
    this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));
  },
  update: function(position) {
    this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
      return m+(Math.round(this._base[i]+(this._delta[i]*position)).toColorPart()); }.bind(this)) });
  },
  finish: function() {
    this.element.setStyle(Object.extend(this.oldStyle, {
      backgroundColor: this.options.restorecolor
    }));
  }
});

Effect.ScrollTo = Class.create();
Object.extend(Object.extend(Effect.ScrollTo.prototype, Effect.Base.prototype), {
  initialize: function(element) {
    this.element = $(element);
    this.start(arguments[1] || {});
  },
  setup: function() {
    Position.prepare();
    var offsets = Position.cumulativeOffset(this.element);
    if(this.options.offset) offsets[1] += this.options.offset;
    var max = window.innerHeight ? 
      window.height - window.innerHeight :
      document.body.scrollHeight - 
        (document.documentElement.clientHeight ? 
          document.documentElement.clientHeight : document.body.clientHeight);
    this.scrollStart = Position.deltaY;
    this.delta = (offsets[1] > max ? max : offsets[1]) - this.scrollStart;
  },
  update: function(position) {
    Position.prepare();
    window.scrollTo(Position.deltaX, 
      this.scrollStart + (position*this.delta));
  }
});

/* ------------- combination effects ------------- */

Effect.Fade = function(element) {
  element = $(element);
  var oldOpacity = element.getInlineOpacity();
  var options = Object.extend({
  from: element.getOpacity() || 1.0,
  to:   0.0,
  afterFinishInternal: function(effect) { 
    if(effect.options.to!=0) return;
    effect.element.hide();
    effect.element.setStyle({opacity: oldOpacity}); 
  }}, arguments[1] || {});
  return new Effect.Opacity(element,options);
}

Effect.Appear = function(element) {
  element = $(element);
  var options = Object.extend({
  from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
  to:   1.0,
  // force Safari to render floated elements properly
  afterFinishInternal: function(effect) {
    effect.element.forceRerendering();
  },
  beforeSetup: function(effect) {
    effect.element.setOpacity(effect.options.from);
    effect.element.show(); 
  }}, arguments[1] || {});
  return new Effect.Opacity(element,options);
}

Effect.DropOut = function(element) {
  element = $(element);
  var oldStyle = {
    top: element.getStyle('top'),
    left: element.getStyle('left'),
    opacity: element.getInlineOpacity() };
  return new Effect.Parallel(
    [ new Effect.Move(element, {x: 0, y: 100, sync: true }), 
      new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
    Object.extend(
      { duration: 0.5,
        beforeSetup: function(effect) {
          effect.effects[0].element.makePositioned(); 
        },
        afterFinishInternal: function(effect) {
          effect.effects[0].element.hide();
          effect.effects[0].element.undoPositioned();
          effect.effects[0].element.setStyle(oldStyle);
        } 
      }, arguments[1] || {}));
}

Effect.SlideDown = function(element) {
  element = $(element);
  element.cleanWhitespace();
  // SlideDown need to have the content of the element wrapped in a container element with fixed height!
  var oldInnerBottom = $(element.firstChild).getStyle('bottom');
  var elementDimensions = element.getDimensions();
  return new Effect.Scale(element, 100, Object.extend({ 
    scaleContent: false, 
    scaleX: false, 
    scaleFrom: window.opera ? 0 : 1,
    scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
    restoreAfterFinish: true,
    afterSetup: function(effect) {
      effect.element.makePositioned();
      effect.element.firstChild.makePositioned();
      if(window.opera) effect.element.setStyle({top: ''});
      effect.element.makeClipping();
      effect.element.setStyle({height: '0px'});
      effect.element.show(); },
    afterUpdateInternal: function(effect) {
      effect.element.firstChild.setStyle({bottom:
        (effect.dims[0] - effect.element.clientHeight) + 'px' }); 
    },
    afterFinishInternal: function(effect) {
      effect.element.undoClipping(); 
      // IE will crash if child is undoPositioned first
      if(/MSIE/.test(navigator.userAgent) && !window.opera){
        effect.element.undoPositioned();
        effect.element.firstChild.undoPositioned();
      }else{
        effect.element.firstChild.undoPositioned();
        effect.element.undoPositioned();
      }
      effect.element.firstChild.setStyle({bottom: oldInnerBottom}); }
    }, arguments[1] || {})
  );
}

Effect.SlideUp = function(element) {
  element = $(element);
  element.cleanWhitespace();
  var oldInnerBottom = $(element.firstChild).getStyle('bottom');
  return new Effect.Scale(element, window.opera ? 0 : 1,
   Object.extend({ scaleContent: false, 
    scaleX: false, 
    scaleMode: 'box',
    scaleFrom: 100,
    restoreAfterFinish: true,
    beforeStartInternal: function(effect) {
      effect.element.makePositioned();
      effect.element.firstChild.makePositioned();
      if(window.opera) effect.element.setStyle({top: ''});
      effect.element.makeClipping();
      effect.element.show(); },  
    afterUpdateInternal: function(effect) {
      effect.element.firstChild.setStyle({bottom:
        (effect.dims[0] - effect.element.clientHeight) + 'px' }); },
    afterFinishInternal: function(effect) {
      effect.element.hide();
      effect.element.undoClipping();
      effect.element.firstChild.undoPositioned();
      effect.element.undoPositioned();
      effect.element.setStyle({bottom: oldInnerBottom}); }
   }, arguments[1] || {})
  );
};

['setOpacity','getOpacity','getInlineOpacity','forceRerendering','setContentZoom',
 'collectTextNodes','collectTextNodesIgnoreClass','childrenWithClassName'].each( 
  function(f) { Element.Methods[f] = Element[f]; }
);

Element.Methods.visualEffect = function(element, effect, options) {
  s = effect.gsub(/_/, '-').camelize();
  effect_class = s.charAt(0).toUpperCase() + s.substring(1);
  new Effect[effect_class](element, options);
  return $(element);
};

Element.addMethods();
var transcrollB_img = "/*include/images/scrollback.gif";
var transcrollF_img = "/*include/images/scrollforward.gif";
var transcrollU_img = "/*include/images/scrollup.gif";
var transcrollD_img = "/*include/images/scrolldown.gif";
var transpix_img    = "/*include/images/transpix.gif";

var g_hashRef = document.location.href.split("#")[1];
var g_preloadArray = new Array();

function $GALLERY(id) 
{
    var gallery = null;
    try {gallery = eval("Gallery_" + id);}
    catch (e) {}
    return gallery;
}

function galItemPreload(galIdx)                { $GALLERY(galIdx).preloadImages();             }
function galItemEnlarge(galIdx,thmbIdx,ss,ps)  { $GALLERY(galIdx).swapEnlarged(thmbIdx,ss,ps); }
function galItemTrueSize(galIdx)               { $GALLERY(galIdx).showTrueSize();              }
function galItemBack(galIdx)                   { $GALLERY(galIdx).stepBack();                  }
function galItemToggleShow(galIdx)             { $GALLERY(galIdx).toggleShow();                }
function galItemForward(galIdx)                { $GALLERY(galIdx).stepForward();               }
function galItemRSS(galIdx, uri)               { $GALLERY(galIdx).getRSSFeed(uri);             }
function galItemScrollBack(galIdx)             { $GALLERY(galIdx).scrollBack();                }
function galItemScrollForward(galIdx)          { $GALLERY(galIdx).scrollForward();             }
function galItemScrollForward(galIdx)          { $GALLERY(galIdx).scrollForward();             }
function galItemCloseOverlay(galIdx)           { $GALLERY(galIdx).closeOverlay();              }
function galItemThumbIndex(galIdx)             { return $GALLERY(galIdx).getThumbIdx();        }

function tLnkIcn(lnk, doShow)
{
   for (var i = 0; i < lnk.childNodes.length; i++)
   {
       if (lnk.childNodes[i].tagName == "IMG")
       {
           lnk.childNodes[i].style.visibility = (doShow ? "visible" : "hidden");
           break;
       }
   }
}

var ThmbLnk = Class.create();
ThmbLnk.prototype = {
	initialize       : function(galDivId, idx, enlargeAction) { 
        this.idx = idx;
        this.galDivId = galDivId; 
        this.linkid = "b_" + idx + galDivId;
        this.isMO = enlargeAction && (enlargeAction.toLowerCase() == "mouseover");
        Event.observe(this.linkid, enlargeAction, this.enlargeThmbLnk.bind(this));
    },
    enlargeThmbLnk : function () { galItemEnlarge(this.galDivId, this.idx, false, !this.isMO);}
}

Object.extend(Element, {
	getWidth: function(element) {
	   	element = $(element);
        var w = element.style.width;
        return ((!w || w==undefined || w==null) ? parseInt(0) : (w.indexOf("px") > -1 ? parseInt(w.substring(0, w.length - 2)) : parseInt(w)));
	}
});

var PhotoGallery = Class.create();
PhotoGallery.prototype = {
	initialize : function(id, galArray, layoutStyle, orientation, doFade, enlargeAction, visThmbs, hideCaption, bgColor, playImg, pauseImg, playAlt, pauseAlt) { 
        this.galDivId = id;

        // Find requested thumbnail for this gallery if it is on the URL
        var galRef = (g_hashRef ? g_hashRef.split("_")[1] : null);
        var thmbRef  = (galRef == this.galDivId ? (g_hashRef ? g_hashRef.split("_")[0] : null) : 0);
        this.thmbIdx = parseInt(((!thmbRef) ? 0 : thmbRef));

        this.galArray = galArray;
        this.layoutStyle = layoutStyle;
        this.enlargedBoxId = "lgBox" + this.galDivId;
        this.enlargedImgId = "lg" + this.galDivId;
        this.titleId = "title" + this.galDivId;
        this.descId = "desc" + this.galDivId;
        this.ssPlayTo = null;
        this.ssPlay = false; 
        this.doFade = doFade;
        this.enlargeAction = enlargeAction;
        this.hideCaption = hideCaption;
        this.bgColor = bgColor;
        this.thmbPage = 1;
        this.visThmbs = visThmbs; // max thumbnails visible; if 0, only enlarged image shows
        this.playImg = playImg;
        this.pauseImg = pauseImg;
        this.playAlt = playAlt;
        this.pauseAlt = pauseAlt;
        this.ppIcnId = "ppicn_" + this.galDivId;

        if (this.layoutStyle == "enlarged")
            Event.observe(document, "keydown", this.processKeyRequest.bind(this));

        this.scrollbId = "scrollb" + this.galDivId;
        this.scrollfId = "scrollf" + this.galDivId;
        this.scrollb_img = (orientation == "horizontal" ? transcrollB_img : transcrollU_img);
        this.scrollf_img = (orientation == "horizontal" ? transcrollF_img : transcrollD_img);

        if (this.visThmbs > 0 && this.galArray.length > this.visThmbs)
        {
            $(this.scrollfId).src = this.scrollf_img;
        }

        if (this.visThmbs > 0)
        {
            for (var cntIdx = 0; cntIdx < this.galArray.length; cntIdx++)
            {            
                // Observe mouseover or click events on the thumbnail links
                new ThmbLnk(this.galDivId, cntIdx, this.enlargeAction);
            }
        }
    },
   
    preloadImages : function () {
        var aIdx = 0;
        for (var cntIdx = 0; cntIdx < this.galArray.length; cntIdx++)
        {            
            // Preload images into a global array
            aIdx = g_preloadArray.length;
            g_preloadArray[aIdx] = new Image();
            g_preloadArray[aIdx].src = this.galArray[cntIdx].src;
        }
    },

    processKeyRequest : function (e) {
        var evt = (e == null ? window.event : e);
        var btn = (evt.which ? evt.which : (evt.keyCode ? evt.keyCode : null));
        if (btn != null)
        {
            if (btn == Event.KEY_LEFT  || btn == Event.KEY_UP) 
                this.stepBack();
            else if (btn == Event.KEY_RIGHT || btn == Event.KEY_DOWN) 
                this.stepForward();
        }
    },

    getThumbIdx : function () { 
        return this.thmbIdx; 
    },

    getNextIdx : function (direction) { 
        return ((direction == -1) ? (this.thmbIdx < 1 ? this.galArray.length-1 : this.thmbIdx-1) : (this.thmbIdx > this.galArray.length - 2 ? 0 : this.thmbIdx+1)); 
    },

    toggleShow : function () {
        if (this.ssPlayTo)
           window.clearTimeout(this.ssPlayTo);

        this.ssPlay = !this.ssPlay;
        if (this.ssPlay)
        {
            $(this.ppIcnId).src = this.pauseImg;
            $(this.ppIcnId).alt = this.pauseAlt;
            this.playShow(2000);
        }
        else
        {
            $(this.ppIcnId).src = this.playImg;
            $(this.ppIcnId).alt = this.playAlt
        }
    },

    playShow : function (intvl) {
        if (this.ssPlay)
        {
            var newIdx = this.getNextIdx(1);
            this.ssPlayTo = window.setTimeout("galItemEnlarge('" + this.galDivId + "'," + newIdx + ",true,false)", intvl);
        }
    },

    deselectCurrent : function () {
        var curItem = this.galArray[this.thmbIdx];
        if (this.visThmbs > 0)
        {
            var curThmb = document.getElementById(curItem.id+"_"+this.galDivId);
            new Element.ClassNames(curThmb);
            curThmb.removeClassName('TG_thmbImgCur');      
        }
        $(this.enlargedImgId).hide();
    }, 

    swapEnlarged : function(newIdx, isSSRequest, pauseSS) {
        var reqItem = this.galArray[newIdx];
        var currSrc = $(this.enlargedImgId).src;
        var isDifferent = this.layoutStyle == "lightbox" ||  this.thmbIdx != newIdx || (currSrc && currSrc.indexOf("transpix") > -1);
        if (isDifferent && (!this.ssPlay || pauseSS || isSSRequest))
        {
            if (!isSSRequest && this.ssPlay) 
            {
                // auto pause slideshow when a button click requests a 
                // different image before swapping the current image
                this.toggleShow();
            }
            this.deselectCurrent();
            this.thmbIdx = newIdx;
            this.enlarge();
        }
    },

    enlarge : function () {
        var curItem = this.galArray[this.thmbIdx];
        if (curItem.filterPrefix && curItem.filterPrefix.length > 0)
        {
            $(this.enlargedImgId).src = transpix_img;
            $(this.enlargedImgId).style.filter = curItem.filterPrefix + escape(curItem.src) + curItem.filterSuffix;
        }
        else
        {
            $(this.enlargedImgId).src = curItem.src;
            $(this.enlargedImgId).style.filter = "";
        }
        $(this.enlargedImgId).title = curItem.title;
        $(this.enlargedImgId).alt = curItem.alt;
        $(this.enlargedImgId).style.width = curItem.width;
        $(this.enlargedImgId).style.height = curItem.height;

        // caption may be hidden so check before modifying
        if (! this.hideCaption)
        {
            $(this.titleId).innerHTML = curItem.title;
            $(this.descId).innerHTML = curItem.descr;
        }

        // all thumbs may be hidden so check before modifying thumb
        if (this.visThmbs > 0 && this.layoutStyle != "lightbox")
        {
            var curThmb = document.getElementById(curItem.id+"_"+this.galDivId); 
            new Element.ClassNames(curThmb);
            curThmb.addClassName('TG_thmbImgCur');
        }
        // Not fully implemented for all browsers
        if (this.layoutStyle == "lightbox" && $(this.enlargedBoxId).style.display == "none")
            this.openOverlay();

        if (this.doFade) new Effect.Appear(this.enlargedImgId, {duration: 0.3, queue: 'parallel'});
        else $(this.enlargedImgId).show();

        // all thumbs may be hidden so check first before attempting to scroll thumbs
        if (this.visThmbs > 0)
        {
            var tPage = Math.floor((this.thmbIdx / this.visThmbs) + 1);
            if (tPage > this.thmbPage) this.scrollForward();
            else if (tPage < this.thmbPage) {
                // detect when cycling around to beginning of thumbnails and set this.thmbPage to 2 
                // so we effectively go to page 1 by  scrolling back from page 2
                if (tPage == 1 && this.thmbPage != 2) this.thmbPage = 2; 
                this.scrollBack(); 
            }
        }
        this.playShow(3000);
    },
    scrollBack  : function () {
        if(this.thmbPage != 1) {
            this.thmbPage--;
        }

        var endImage = this.thmbPage * this.visThmbs;
        var startImage = endImage - (this.visThmbs - 1);

        if(this.thmbPage == 1) {
            $(this.scrollbId).src = transpix_img;
        }

        if (endImage > this.galArray.length) {
            endImage = this.galArray.length;
        }

        var imgId;
        // Hide all the thumbs
        for(var i=0; this.galArray.length > i; i++) {
            $('b_' + i + this.galDivId).hide();
        }

        // Show the ones we want
        for(var i=startImage-1; endImage > i; i++) {
            $('b_' + i + this.galDivId).show();
        }

        $(this.scrollfId).src = this.scrollf_img;
    },
    scrollForward  : function () {
        if(this.thmbPage * this.visThmbs < this.galArray.length) {
            this.thmbPage++;
        };

        var endImage = this.thmbPage * this.visThmbs;
        var startImage = endImage - (this.visThmbs - 1);

        if (endImage >= this.galArray.length) {
            endImage = this.galArray.length;
            $(this.scrollfId).src = transpix_img;
        }

        // Hide all the thumbs
        for(var i=0; this.galArray.length > i; i++) {
            $('b_' + i + this.galDivId).hide();
        }

        // Show the ones we want
        for(var i=startImage-1; endImage > i; i++) {
            $('b_' + i + this.galDivId).show();
        }

        this.loadThumbs(startImage, endImage);

        $(this.scrollbId).src = this.scrollb_img;

    },
    getRSSFeed  : function (uri) {
        window.open(uri, "galleryDetail");
    },
    showTrueSize  : function () {
        var curItem = this.galArray[this.thmbIdx];
        try {
        window.open(curItem.osrc, "galleryDetail");
        }
        catch(e) {
        window.open(curItem.src, "galleryDetail");
        }
    },
    stepForward  : function () {
        this.swapEnlarged(this.getNextIdx(1), false, true);
    },
    stepBack  : function () {
        this.swapEnlarged(this.getNextIdx(-1), false, true);
    },
    loadThumbs : function (startImage, endImage) {
        var endImage = endImage;
        var startImage = startImage;

        if (endImage >= this.galArray.length) {
            endImage = this.galArray.length;
        }
    },

    openOverlay : function () {
        this.hideAlwaysOnTop();

		var pageDims = getPageSize();
		var pageScrollDims = getPageScroll();

        var pageShadow = document.getElementById('TGPageShadow');
        var isNew = !pageShadow;
        if (isNew)
        {
            pageShadow = document.createElement("div");
            pageShadow.setAttribute('id','TGPageShadow');
        }
        pageShadow.style.display = 'none';
		pageShadow.style.position = 'absolute';
		pageShadow.style.top = '0px';
		pageShadow.style.left = '0px';
		pageShadow.style.textAlign = 'left';
		pageShadow.style.zIndex = 998;
		pageShadow.style.backgroundColor = '#000000';
		pageShadow.style.width =  pageDims[0] + "px";
		pageShadow.style.height = pageDims[1] + "px";


		if (isNew) document.getElementsByTagName("body").item(0).appendChild(pageShadow);
		new Effect.Appear('TGPageShadow', { duration: 0.2, from: 0.0, to: 0.8 });
        Event.observe('TGPageShadow', "click", this.closeOverlay.bind(this));


        var floater = document.getElementById('TGFloater');
        if (!floater)
        {
            floater = document.createElement("div");
            floater.setAttribute('id','TGFloater');
        }
		floater.style.display = 'none';
		floater.style.position = 'absolute';
		floater.style.top = '0px';
		floater.style.left = '0px';
		floater.style.textAlign = 'center';
		floater.style.zIndex = 999;
		if (isNew) document.getElementsByTagName("body").item(0).appendChild(floater);

		floater.style.width = $(this.enlargedBoxId).style.width;
		floater.style.height = $(this.enlargedBoxId).style.height;
		floater.style.backgroundColor = this.bgColor;
		
        floater.appendChild($(this.enlargedBoxId));

		var floaterTop = pageScrollDims[1] + parseInt((pageDims[3] / 10));
		var floaterLeft = pageScrollDims[0] + parseInt((pageDims[0] - Element.getWidth(this.enlargedBoxId)) / 2);
		floater.style.top = floaterTop + "px";
		floater.style.left = floaterLeft + "px";
        $('TGFloater').show();
        $(this.enlargedBoxId).show();
        Event.observe(document, "keydown", this.processKeyRequest.bind(this));


    },

    closeOverlay : function () {
        // Stop the slideshow
        if (this.ssPlay) this.toggleShow();
        // Hide the enlarged box containing images and caption
        $(this.enlargedBoxId).hide();
        $('TGFloater').hide();
        // Move the enlarged image box back to the main document  
        // body in case there are other lightbox galleries
        var tgcontent = document.getElementById('TGBodyOrigin');
        tgcontent.appendChild($(this.enlargedBoxId));        
        // Fade out the page shadowing
        new Effect.Fade('TGPageShadow', { duration: 0.2});
        // Show "always on top" objects again
        this.showAlwaysOnTop();
    },

    showAlwaysOnTop : function () {
        toggleVisByTagType("select", "visible");
        toggleVisByTagType("object", "visible");
        toggleVisByTagType("embed", "visible");
    },

    hideAlwaysOnTop : function () {
        toggleVisByTagType("select", "hidden");
        toggleVisByTagType("object", "hidden");
        toggleVisByTagType("embed", "hidden");
    }
}

function toggleVisByTagType(tagName, vis)
{
    var els = document.getElementsByTagName(tagName);
    for (i = 0; i != els.length; i++) {
       els[i].style.visibility = vis;
    }
}

//
// getPageScroll()
// Returns array with x,y page scroll values.
// Core code from - quirksmode.com
//
function getPageScroll(){

	var xScroll, yScroll;

	if (self.pageYOffset) {
		yScroll = self.pageYOffset;
		xScroll = self.pageXOffset;
	} else if (document.documentElement && document.documentElement.scrollTop){	 // Explorer 6 Strict
		yScroll = document.documentElement.scrollTop;
		xScroll = document.documentElement.scrollLeft;
	} else if (document.body) {// all other Explorers
		yScroll = document.body.scrollTop;
		xScroll = document.body.scrollLeft;	
	}

	arrayPageScroll = new Array(xScroll,yScroll) 
	return arrayPageScroll;
}

//
// getPageSize()
// Returns array with page width, height and window width, height
// Core code from - quirksmode.com
// Edit for Firefox by pHaez
//
function getPageSize(){
	
	var xScroll, yScroll;
	
	if (window.innerHeight && window.scrollMaxY) {	
		xScroll = window.innerWidth + window.scrollMaxX;
		yScroll = window.innerHeight + window.scrollMaxY;
	} else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
		xScroll = document.body.scrollWidth;
		yScroll = document.body.scrollHeight;
	} else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
		xScroll = document.body.offsetWidth;
		yScroll = document.body.offsetHeight;
	}
	
	var windowWidth, windowHeight;

	if (self.innerHeight) {	// all except Explorer
		if(document.documentElement.clientWidth){
			windowWidth = document.documentElement.clientWidth; 
		} else {
			windowWidth = self.innerWidth;
		}
		windowHeight = self.innerHeight;
	} else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
		windowWidth = document.documentElement.clientWidth;
		windowHeight = document.documentElement.clientHeight;
	} else if (document.body) { // other Explorers
		windowWidth = document.body.clientWidth;
		windowHeight = document.body.clientHeight;
	}	
	
	// for small pages with total height less then height of the viewport
	if(yScroll < windowHeight){
		pageHeight = windowHeight;
	} else { 
		pageHeight = yScroll;
	}

	// for small pages with total width less then width of the viewport
	if(xScroll < windowWidth){	
		pageWidth = xScroll;		
	} else {
		pageWidth = windowWidth;
	}

	arrayPageSize = new Array(pageWidth,pageHeight,windowWidth,windowHeight) 
	return arrayPageSize;
}


var TGGallery_gTitleObj = null;
var TGGallery_gTitleTimer = null;

function TGGallery_showTitle(titleObj)
{
    if (TGGallery_gTitleTimer)
        clearTimeout(TGGallery_gTitleTimer);
    
    if (TGGallery_gTitleObj)
        TGGallery_titleDetail(TGGallery_gTitleObj);
    
    TGGallery_gTitleObj = titleObj;
    TGGallery_gTitleTimer = setTimeout("TGGallery_titleDetail(null,true);", 500);
}

function TGGallery_titleDetail(titleObj, reveal, e)
{
    var evtElement = null;

    if (e && TGGallery_gTitleObj)
    {
        if (e.target)
            evtElement = e.target;
        else
            evtElement = e.srcElement;
    }
    var title = (titleObj ? titleObj : TGGallery_gTitleObj);
    if (reveal)
    {
        with (title.style)
        {
            border = "#333 solid 1px";
            background = "#ffffe8";
            overflow = "";
            whiteSpace = "normal";
            textDecoration = "none";
        }
    }
    else
    {
        with (title.style)
        {
            border = "none";
            background = "transparent";
            whiteSpace = "nowrap";
            overflow = "hidden";
            textDecoration = "underline";            
        }
        TGGallery_gTitleObj = null;
        clearTimeout(TGGallery_gTitleTimer);            
    }
}

// View-Side Functions used by the TG Mortgage Calculator Widget
function TG_MCMortCal(l,i,n)
{
	if(document.mort.loan.value=="") {
	   alert(gErrNoLoanAmt);
	   document.mort.loan.focus();
	   return false;
	}
	else if(isNaN(document.mort.loan.value)) {
	   alert(gErrNonNumericLoanAmt);
	   document.mort.loan.focus();
	   return false;
	}
	else if(document.mort.interest.value=="") {
	   alert(gErrNoInterest);
	   document.mort.interest.focus();
	   return false;
	}
	else if(isNaN(document.mort.interest.value)) {
	   alert(gErrNonNumericInterest);
	   document.mort.interest.focus();
	   return false;
	}
	else if(document.mort.interest.value > 50 || document.mort.interest.value < 0) {
	   alert(gErrInvalidRate);
	   document.mort.interest.focus();
	   return false;
	}   
	else if(document.mort.period.value=="") {
	   alert(gErrNoPeriod);
	   document.mort.period.focus();
	   return false;
	}  
	else if(isNaN(document.mort.period.value)) {
	   alert(gErrNonNumericPeriod);
	   document.mort.period.focus();
	   return false;
	}

	var P= 0.0;
	var c=0.0;
	c = i / 1200;
	var nn=0.0;
	nn = n * 12;
	P = l * Math.pow((1 + c), nn) * c / (Math.pow((1 + c), nn) - 1);
	P=Math.round(P * 100)/100;
	P=TG_MCFixedRate(P);
	document.mort.payment.value=(P < 0) ? "0.00" : P;
	document.othm.ymp.value=(P < 0) ? "0.00" : P;
}

function TG_MCVerify(f) 
{
    var msg;
    var empty_fields = "";
    var errors = "";

    for(var i = 0; i < f.length; i++)
    {
        var e = f.elements[i];
        if (e.type == "text") 
        {
            if (e.value != "") 
            {
                var v = parseFloat(e.value);

                if (isNaN(v) || 
                   ((e.min != null) && (v < e.min)) ||
                   ((e.max != null) && (v > e.max))) 
                {
                    alert(gErrNonNumeric);
                    e.focus();
                    return false;
                }   	
            }
        }
    }
    return true;
}

function TG_MCFixedRate(n) 
{
    var n2= '"' + ((n*100)/100) + '"';
    var arr = n2.split(".");
    var d=arr[0];
    var c=(arr[1]==null) ? '0' : arr[1].substr(0,3); 
    n2=((c=='0') ? d.substr(1,(d.length - 2)) : d.substr(1)) + '.' + ( (c.length <=2) ? (c.substr(0,1) + 0) : c.substr(0,(c.length-1)) );
    return n2;
}

function TG_MCGetHowMuch() 
{
    if (!TG_MCVerify(document.howm)) 
        return;

    var b  = new Array();
    var cb = new Array();
    var inc=0;
    var exp=0;

    var bkratio=39/100;   
    var netinc;
    var pretaxinc;
    var exp;
    var apay; 
    var hins=document.howm.bhins.value.replace(/,/g, "");
    var htax=document.howm.bptax.value.replace(/,/g, "");

    b[0]=0; 
    b[1]=document.howm.bwages.value.replace(/,/g, "");
    b[2]=document.howm.bdiv.value.replace(/,/g, "");
    b[3]=document.howm.both.value.replace(/,/g, "");
    b[4]=0;
    b[5]=0;

    cb[0]=0;
    cb[1]= document.howm.cbwages.value.replace(/,/g, "");
    cb[2]= document.howm.cbdiv.value.replace(/,/g, "");
    cb[3]= document.howm.cboth.value.replace(/,/g, "");
    cb[4]=0;
    cb[5]=0;

    var be  = new Array();
    var cbe = new Array();

    be[0]=0;
    be[1]= document.howm.bins.value.replace(/,/g, "");
    be[2]= document.howm.bauto.value.replace(/,/g, "");
    be[3]= document.howm.bcc.value.replace(/,/g, "");
    be[4]= document.howm.bsav.value.replace(/,/g, "");
    be[5]= document.howm.beoth.value.replace(/,/g, "");

    cbe[0]=0;
    cbe[1]= document.howm.cbins.value.replace(/,/g, "");
    cbe[2]= document.howm.cbauto.value.replace(/,/g, "");
    cbe[3]= document.howm.cbcc.value.replace(/,/g, "");
    cbe[4]= document.howm.cbsav.value.replace(/,/g, "");
    cbe[5]= document.howm.cbeoth.value.replace(/,/g, "");

    for (var i=1; i<6; i++)
    {
         b[i] = b[i]=="" ? 0 : b[i];
         b[0] = parseFloat(b[0]) + parseFloat(b[i]);
         cb[i] = cb[i]=="" ? 0 : cb[i];
         cb[0] = parseFloat(cb[0]) + parseFloat(cb[i]);

         be[i] = be[i]=="" ? 0 : be[i];
         be[0] = parseFloat(be[0]) + parseFloat(be[i]);
         cbe[i]= cbe[i]=="" ? 0 : cbe[i];

         cbe[0] = parseFloat(cbe[0]) + parseFloat(cbe[i]);
    }

    pretaxinc=(parseFloat(b[0]) + parseFloat(cb[0]));
    exp=(parseFloat(be[0]) + parseFloat(cbe[0]));

    apay=((pretaxinc * bkratio)-exp) - hins - htax;

    apay=(apay*100)/100;
    apay=TG_MCFixedRate(apay);
    document.howm.cnafrd.value=(apay < 0) ? 0 : apay;
    document.mort.maxcnafrd.value=(apay < 0) ? 0 : apay;

    return false;
}

function TG_MCGetTaxSav(n) 
{
    var s= n * 12 * (document.othm.staxb.value/100);
    document.othm.taxsav.value = TG_MCFixedRate(s);
    return false;
}

function TG_MCClearValues()
{
    document.mort.loan.value="";
    document.mort.interest.value="";
    document.mort.period.value="";
    document.mort.payment.value="";
    document.mort.loan.focus();
}

var TG_masterFooterTop = null;
var TG_needPageFooterTop = false;
var TG_pageFooterTop = null;
var TG_footerItems = new Array();

function TG_calcCurrentPageHeight()
{
   var currPageHeight = 0;
   var currPageOrigin = document.getElementById('TGBodyOrigin');

   if (currPageOrigin)
   {
       var currPageTags = currPageOrigin.getElementsByTagName("*");
       var bY = parseInt(currPageOrigin.style.top,  10);

       for (var i = 0; i < currPageTags.length; i++)
       {
          var curH = (currPageTags[i].offsetTop +  currPageTags[i].offsetHeight);
          if(currPageTags[i].parentNode && currPageTags[i].parentNode.id == "TGBodyOrigin")
          {
              curH += bY;
          }

          currPageHeight = ((curH > currPageHeight) ? curH : currPageHeight);
       }
   }
   return currPageHeight;
}

function TG_offsetFooter(isEditor)
{
    try
    {
        // if the page does not have a precalculated footer top but the master page does, 
        // offset all known masterpage footer items by a value based on bottom of page widgets
        if (TG_needPageFooterTop || TG_masterFooterTop != null)
        {

            var offsetY = (TG_pageFooterTop ? TG_pageFooterTop : TG_calcCurrentPageHeight()) - TG_masterFooterTop;

            if (offsetY > 0)
            {
                if (isEditor)
                {
                    // if we're using this utility function in an authorized edit session, the
                    // TG_footerItems array will not be populated, but the widgets
                    // will have the non-W3C standard isfooter property available
                    var masterPageTags = document.getElementById('TGBodyContent').childNodes;
                    for (var i = 0; i < masterPageTags.length; i++)
                    {
                        if (masterPageTags[i].isfooter == "true")
                            masterPageTags[i].style.pixelTop += offsetY;
                    }

                }
                else if (TG_footerItems.length > 0)
                {
                    for (var i = 0; i < TG_footerItems.length; i++)
                    {
                        document.getElementById(TG_footerItems[i]).style.top = (parseInt(document.getElementById(TG_footerItems[i]).style.top) + offsetY) + "px";
                    }
                }
            }
        }
    }
    catch (e)
    {
        // do nothing if error -- page will display as if no items were placed explicitly in footer
    }
}

var PageExtents = {

    maxHeight: 0,
    maxWidth: 0,

    xtraOffsetTop: 0,
    xtraOffsetLeft: 0,
    doXtraOffset: false,

    logStr: "",
    
    walkNodes: function (rootEl,forcedWidth,forcedHeight)
    {
        var pageTags = rootEl.childNodes;
        
        var curW = 0;
        var curH = 0;
    
        for (var i = 0; i < pageTags.length; i++)
        {
            if (pageTags[i].nodeType == 1 && pageTags[i].style.position == "absolute" && pageTags[i].id !="TGselectionBox")
            {
                //only care about absolutely positioned element nodes
                
                //forced height and forced width are used exclusively by search results page
                if (pageTags[i].id == "TGBodyOrigin" && forcedHeight && !isNaN(forcedHeight) && pageTags[i].offsetHeight>forcedHeight)
                {//if user passed in a forced height, use that height if content is bigger than that. otherwise use content height
                    curH = (pageTags[i].offsetTop + forcedHeight);
                }
                else
                {//if user passed in a forced width, use that width
                    curH = (pageTags[i].offsetTop +  pageTags[i].offsetHeight);                    
                }
                if (pageTags[i].id == "TGBodyOrigin" && forcedWidth && !isNaN(forcedWidth))
                {
                    curW = (pageTags[i].offsetLeft + forcedWidth);
                }
                else
                {
                    curW = (pageTags[i].offsetLeft + pageTags[i].offsetWidth);
                }
                
                if (this.doXtraOffset && 
                    pageTags[i].parentNode && pageTags[i].parentNode.id == "tgcontent")
                {
                    curH = curH + this.xtraOffsetTop;
                    curW = curW + this.xtraOffsetLeft;
                }
                
                this.maxHeight = curH > this.maxHeight ? curH : this.maxHeight;
                this.maxWidth  = curW > this.maxWidth  ? curW : this.maxWidth;
                
                if (pageTags[i].style.overflow != "scroll" && 
                    pageTags[i].style.overflow != "hidden")
                {
                    this.walkNodes(pageTags[i],forcedWidth,forcedHeight);
                }
            }
        }
    },
    
    calculate: function (rootNode, offsetNode, forcedWidth,forcedHeight)
    {
        if (rootNode)
        {
            this.maxHeight = 0;
            this.maxWidth = 0;

            if (offsetNode)
            {
               this.xtraOffsetLeft = (offsetNode ? parseInt(offsetNode.style.left, 10) : 0);
               this.xtraOffsetTop =  (offsetNode ? parseInt(offsetNode.style.top,  10) : 20);
               this.doXtraOffset = true;
            }
            else
            {
                this.xtraOffsetTop = 0;
                this.xtraOffsetLeft = 0;
                this.doXtraOffset = false;
            }

            this.walkNodes(rootNode,forcedWidth,forcedHeight);
            
        }
        else throw new Error("PageExtents.calculate() Missing argument: rootNode");
    }
}



function TG_changeCalDate(changeQuery)
{
   var prevQuery = location.search;
   var newQuery = "";

   if (prevQuery && prevQuery.length > 1 && prevQuery.substring(0,1) == "?")
   {
       prevQuery = prevQuery.substring(1);
       var argArray = prevQuery.split("&");
       for (var idx = 0; idx < argArray.length; idx++)
       {
           if ((argArray[idx].indexOf("ys=") == -1) &&
               (argArray[idx].indexOf("ms=") == -1) &&
               (argArray[idx].indexOf("ws=") == -1) &&
               (argArray[idx].indexOf("ds=") == -1) &&
               (argArray[idx].indexOf("vw=") == -1) &&
               (argArray[idx].indexOf("tgname=") == -1))
           {
               newQuery += (newQuery.length ? "&" : "?") + argArray[idx];
           }
       }
    }

    newQuery += (newQuery.length ? "&" : "?") + changeQuery;

    try
    {
        if (gNXGStoreTemplate != null)
            location = TGSite.getDefaultDomain() + "/" + gNXGStoreTemplate + newQuery;
    }
    catch (e)
    {
        location.search = newQuery;
    }

    return false;
}

function TG_changeTimeZone(tzidSelected)
{
   var prevQuery = location.search;
   var newQuery = "";

   if (prevQuery && prevQuery.length > 1 && prevQuery.substring(0,1) == "?")
   {
       prevQuery = prevQuery.substring(1);
       var argArray = prevQuery.split("&");
       for (var idx = 0; idx < argArray.length; idx++)
       {
           if (argArray[idx].indexOf("tzid=") == -1)
           {
               newQuery += (newQuery.length ? "&" : "?") + argArray[idx];
           }
       }
    }

    newQuery += (newQuery.length ? "&" : "?") + "tzid="+tzidSelected;

    // Set a cookie for the preferred time zone
    var domain = document.domain.substr(document.domain.indexOf("."));
    var cookieStr = "TG_TIMEZONE="+tzidSelected+";expires=Sat, 11 Jun 2011 11:59:59 UTC ;domain="+domain;
    document.cookie = cookieStr;

    try
    {
        if (gNXGStoreTemplate != null)
            location = TGSite.getDefaultDomain() + "/" + gNXGStoreTemplate + newQuery;
    }
    catch (e)
    {
        location.search = newQuery;
    }

    return false;
}


if (gVersionId == "null" || gVersionId == "")
{
    var win = window;
    var winName=win.name;
    while (win != null && winName!="" && winName.indexOf("_TGVersionPreview") == -1)
        {       
            win = win.opener;
            try
            {
                winName=win.name;  //sometimes throws access is denied error when trying to access win.name of an openning window, sometimes only throws error if accessing with win.name.indexOf
            }
            catch (e)
            {
                winName="";
            }
        }

    if (win != null && winName!="" && winName.indexOf("_TGVersionPreview") == 0)        
        gVersionId = winName.substring(17);
    else  
        gVersionId = "";

    if (gVersionId != "")
    {
        try 
        {
            if (location.search.indexOf("?") == -1)
                location.search = location.search + "?nxg_versionuid=" + gVersionId;
            else if (location.search.indexOf("nxg_versionuid") == -1)
                location.search = location.search + "&nxg_versionuid=" + gVersionId;
        }
        catch(e)
        {
        }
    }
}

function TG_fixActiveX()
{
    if (isIE && isWindows)
    {
//information about this hack can be found at 
//http://msdn.microsoft.com/workshop/author/dhtml/overview/activating_activex.asp
try
{
    var tagArray = new Array("OBJECT","EMBED","APPLET");
    for (var k = 0; k < tagArray.length; k++)
    {
        var tags = document.getElementsByTagName(tagArray[k]);
        for (var i = 0; i < tags.length; i++)
        {
            try 
            {
                var isFlash = false;
                var startStr = tags[i].outerHTML.substring(0,tags[i].outerHTML.indexOf(">")+1);
                for (var j = 0; j < tags[i].childNodes.length; j++)
                {
					if (tags[i].childNodes[j].getAttribute("name") == "movie")
					{
						//if movie attrib isn't set to default then add it otherwise ignore attrib
						var mvSrc = tags[i].childNodes[j].getAttribute("value");
						if (mvSrc && (mvSrc.indexOf("/*widgets/flash/blank.swf") == -1))
						{
							startStr += tags[i].childNodes[j].outerHTML;
						}
                        isFlash=true;
					}
					else
					{
	                    //if activeX_url attrib exists rewrite it as the movie attrib
	                    //this prevents the "double-loading" appearance
	                    if (tags[i].childNodes[j].getAttribute("name") == "activeX_url")
	                    {
	                    	tags[i].childNodes[j].setAttribute("name","movie");
                            isFlash=true;
	                    }
	                    startStr += tags[i].childNodes[j].outerHTML;
					}
                }
                startStr += "</"+ tagArray[k] +">";
                if (isFlash)
                {//only do this for flash, this is possibly needed to be implemented for other media, but since this was
                //just a bug that occurred during a small time period in IE, likely won't be needed for new media widgets
                tags[i].outerHTML = startStr;
                }
            }
            catch(e){/*ignore*/}
            
        }
    }
}
catch(e){/*ignore*/}
 
    }
}

function TG_fixIEItems()
{
    if (isIE)
    {
        var domEl = null;
        var es = null;
        for (var i = 0; i < TG_itemsToFix.length; i++)
        {
            domEl = document.getElementById(TG_itemsToFix[i]);
            if (domEl != null && domEl.style != null)
            {
                es = domEl.style;
                if (es.pixelWidth || es.pixelWidth == 0)
                    es.pixelWidth = es.pixelWidth + (isNaN(parseInt(es.borderLeftWidth,10)) ? 0 : parseInt(es.borderLeftWidth,10))
                                                  + (isNaN(parseInt(es.borderRightWidth,10)) ? 0 : parseInt(es.borderRightWidth,10))
                                                  + (isNaN(parseInt(es.paddingLeft,10)) ? 0 : parseInt(es.paddingLeft,10))
                                                  + (isNaN(parseInt(es.paddingRight,10)) ? 0 : parseInt(es.paddingRight,10));

                if (es.pixelHeight || es.pixelHeight == 0)
                    es.pixelHeight = es.pixelHeight + (isNaN(parseInt(es.borderTopWidth,10)) ? 0 : parseInt(es.borderTopWidth,10))
                                                  + (isNaN(parseInt(es.borderBottomWidth,10)) ? 0 : parseInt(es.borderBottomWidth,10))
                                                  + (isNaN(parseInt(es.paddingTop,10)) ? 0 : parseInt(es.paddingTop,10))
                                                  + (isNaN(parseInt(es.paddingBottom,10)) ? 0 : parseInt(es.paddingBottom,10));
            }
        }
    }
}


function TG_handleImageChange(el,img,filter)
{//this handles png's that are the background of an element like a div

    if (el)
    {
        el.style.filter = filter;
        if (el.tagName.toLowerCase()=="img")
        {
            el.src=img;
        }
        else
        { 
            el.style.backgroundImage=makeCSSImageURL(img);
        }
    }
}


function makeCSSImageURL(imgsrc)
{
    return ("url(" + imgsrc + ")");

}
var gErrNoLoanAmt          = "You must enter a Loan Amount.";
var gErrNonNumericLoanAmt  = "Loan Amount must be numeric. Please enter a numeric value.";
var gErrNoInterest         = "You must enter an Interest rate.";
var gErrNonNumericInterest = "Interest rate must be numeric. Please enter a numeric value.";
var gErrNoPeriod           = "You must enter a Loan Period.";
var gErrInvalidRate        = "Interest Rate must be less than 51% and greater than 0% (Example: 5.75)";
var gErrNonNumericPeriod   = "Period must be numeric, please enter a numeric value.";
var gErrNonNumeric         = "All fields must be numeric. Please enter valid values.";
var gAnswerAntiSpam        = "You must answer the security question.";
var gRequiredFieldMissing    = "Please fill in all required items.";
var gRequiredCheckboxMissing = "Please fill in all required checkboxes.";
var gRequiredSelectMissing   = "Please fill in all required selection lists.";
var gRequiredRadioMissing    = "Please fill in all required radio buttons.";
var gInvalidEmailAddress     = "E-mail addresses must contain an '@' sign.";
var gValDate1                = "nxg_ValDate";
var gValDate2                = "asAntispamInput";
var gValDate3                = "' type='hidden' ";
var gValDate4                = "input ";
var gValDate5                = "name='";
var gValDate6                = "nxg_Notification";
var TGDTDayLbls = new Array();
TGDTDayLbls[0]="1";
TGDTDayLbls[1]="2";
TGDTDayLbls[2]="3";
TGDTDayLbls[3]="4";
TGDTDayLbls[4]="5";
TGDTDayLbls[5]="6";
TGDTDayLbls[6]="7";
TGDTDayLbls[7]="8";
TGDTDayLbls[8]="9";
TGDTDayLbls[9]="10";
TGDTDayLbls[10]="11";
TGDTDayLbls[11]="12";
TGDTDayLbls[12]="13";
TGDTDayLbls[13]="14";
TGDTDayLbls[14]="15";
TGDTDayLbls[15]="16";
TGDTDayLbls[16]="17";
TGDTDayLbls[17]="18";
TGDTDayLbls[18]="19";
TGDTDayLbls[19]="20";
TGDTDayLbls[20]="21";
TGDTDayLbls[21]="22";
TGDTDayLbls[22]="23";
TGDTDayLbls[23]="24";
TGDTDayLbls[24]="25";
TGDTDayLbls[25]="26";
TGDTDayLbls[26]="27";
TGDTDayLbls[27]="28";
TGDTDayLbls[28]="29";
TGDTDayLbls[29]="30";
TGDTDayLbls[30]="31";
function TGDT_ChangeDaysInMonth(domId){ var daysInMonth = TGDT_GetDays(new Date(TGDT_GetYear(domId), TGDT_GetMonth(domId), 1)); var dayEl = document.getElementById(domId+"_date"); if (dayEl) {  var selDay = dayEl.selectedIndex;  dayEl.options.length = 0;  for (var i = 0; i < daysInMonth; i++)  {dayEl.options[i] = new Option(TGDTDayLbls[i],i+1,false);  dayEl.options[i].style.fontSize=dayEl.style.fontSize;dayEl.options[i].style.fontFamily=dayEl.style.fontFamily;}  dayEl.selectedIndex = (selDay > (daysInMonth-1) ? daysInMonth-1 : selDay);}}
function TGDT_GetDays(desiredDate){ var retVal; var now = new Date(); var millisPerDay = 24 * 60 * 60 * 1000; var desiredMonth = desiredDate.getMonth(); var desiredYear = desiredDate.getFullYear(); now.setMonth(desiredMonth+1); do {  now.setTime(now.getTime() - millisPerDay);  retVal = now.getDate();  } while (desiredMonth != now.getMonth()) if (((desiredYear % 4 ) == 0) && ((desiredYear % 1000 ) != 0) && (desiredMonth == 1)) retVal++; return retVal;}
function TGDT_GetMonth(domId) {  if (document.getElementById(domId+"_month")) return document.getElementById(domId+"_month").selectedIndex;  else return "";}
function TGDT_GetYear(domId) { var yearEl = document.getElementById(domId+"_year"); if (yearEl) {  var selIdx = yearEl.selectedIndex;  return yearEl.options[yearEl.selectedIndex].text; } else return "";}
function TGDT_InitDays() { var id = ""; var allEls; var allForms = document.forms; var regExp = /_date/; for (var i = 0; i < allForms.length; i++) {  allEls = allForms[i].elements;  for (var j = 0; j < allEls.length; j++)  {   if (allEls[j].name && regExp.test(allEls[j].name))   {    TGDT_ChangeDaysInMonth(allEls[j].name.replace(regExp,""));   }  } }}

var TGContactInfo = {getValue: function (fieldName){var fieldValue;switch(fieldName){case "title":fieldValue = "";break;case "name":fieldValue = "Andrea";break;case "surname":fieldValue = "Springeld";break;case "email":fieldValue = "";break;case "phone":fieldValue = "2122333538";break;case "fax":fieldValue = "";break;case "company":fieldValue = "M Zion Security Systems Corporation";break;case "street_address_1":fieldValue = "";break;case "street_address_2":fieldValue = "";break;case "city":fieldValue = "New York";break;case "state":fieldValue = "NY";break;case "zip_code":fieldValue = "10038";break;case "country":fieldValue = "";break;}return fieldValue;}};
var TGSite = {getSiteName: function () {return "mzioncom";},getDefaultDomain: function () {return "http://mzioncom.nxg.superpageshosting.com";},getHomePage: function () {return "/home.nxg";}};

