﻿
/************************************** UTILITY */

// TODO: Move all utility functions to a module


// addLoadEvent
//
// Adds a function to the page's onLoad event while preserving any existing functions in the queue
// The function will fire after any existing functions
// Credit: Jeremey Keith, "Dom Scripting"
//
function addLoadEvent(func) {
    var oldonload = window.onload;
    if (typeof window.onload != 'function') {
        window.onload = func;
    }
    else {
        window.onload = function () {
            oldonload();
            func();
        }
    }
}  


// stringFormat
// 
// Mimics String.Format() in VB.net, except the replacement values are contained in an array
// Example: stringFormat("Hello, {0}. You are {1} years old.", [name, age])
// Returns "Hello, Herb. You are 37 years old." (yikes)
//
function stringFormat(s, values)
{
    for (var i in values) {
        s = s.replace('{' + i + '}', values[i]) 
   } 
   return s
}


// getElementsByClassName
//
// Returns an array of elements with the given tag name and class name
// Example: getElementsByClassName('div', 'foo') returns all elements of the form <div class="foo"> 
//
function getElementsByClassName(targetTagName, targetClassName) {
    if (!document.getElementsByTagName) return false; 
    var matchingElements = document.getElementsByTagName(targetTagName);
    var results = new Array();
    var i = 0;
    // Go through all elements with the specified tag name 
    for (var j in matchingElements) {
        var matchingElement = matchingElements[j];
        if (matchingElement.className) {
            // Go through all classnames for this element (class names can be separated by spaces, e.g. <div class="foo bar boo"> )
            var classNamesArray = matchingElement.className.split(" ");
            for (k in classNamesArray) {
                if (classNamesArray[k] == targetClassName) {
                    // Got a match - add to results 
                    results[i++] = matchingElement;
                } 
            }
        }
    }
    return results;
}


// changeClassName
//
// Replaces the "before" class with the "after" class in the target element.
// If the "before" class isn't one of the target element's classes, the "after" class is appended to the class list.
//
// Example: changeClassName(foo, "HighlightOff", "HighlightOn") 
// Changes <div class="BigDiv HighlightOff Green"> to <div class="BigDiv HighlightOn Green">
// Changes <div class="BigDiv"> to <div class="BigDiv HighlightOn">
//
function changeClassName(targetElement, classNameBefore, classNameAfter)
{
    var found = false;
    var classNamesArray = new Array();
    if (typeof(targetElement) != 'object') { targetElement = document.getElementById(targetElement) } // Accept ID of element (string) or the element itself
    if (targetElement.className) {
        // Go through all classnames for this element (class names can be separated by spaces, e.g. <div class="foo bar boo"> )
        classNamesArray = targetElement.className.split(" ");
        for (i in classNamesArray) {
            if (classNamesArray[i] == classNameBefore) {
                // Found the "before" class, clear it out
                classNamesArray[i] = "";
            } 
        }
    }
    classNamesArray.push(classNameAfter); // add the "after" class (whether or not the "before" class was found
    // Put everything back into a single string 
    targetElement.className = classNamesArray.join(" ");
}    

                    
// addRemoteClassChange
//
// Generic function for implementing inobtrusive javascript behaviors by element class (e.g. informational pop-ups, pop-arounds, etc.)
// Finds all elements of a given css class, and attaches event handlers that change the css class on a corresponding element on the page when a given event fires. 
//
// Example: You want mouseovers on one set of divs to change the class of the corresponding element in another set of divs (e.g. to make them visible)
// addRemoteClassChange('div', 'PopAroundTrigger', 'onmouseover', 'PopAroundTrigger_(\d*)', 'PopAroundTarget_$1', 'HighlightOff', 'HighlightOn')
// What this does: 
//      - finds divs of class PopAroundTrigger 
//      - attaches a function to each matching div's mouseover event
//      - that identifies a corresponding div (PopAroundTrigger_Wiki_123 --> PopAroundTarget_Wiki_123)
//      - and changes its class from HighlightOff to HighlightOn
// You would of course want to have a similar call for 'onmouseout' that changes HighlightOn back to HighlightOff.
//
function addRemoteClassChange(
                        triggerTagName, // tag of the trigger elements to wire up (e.g. 'div')
                        triggerClassName, // class of the trigger elements (e.g. 'PopAroundTrigger')
                        triggerEvent, // event to wire up (e.g. 'onmouseover', 'onfocus', 'onmouseout')
                        triggerIdPattern, // regex pattern matching the trigger element's ID, e.g. 'PopAroundTrigger_(\d*)' 
                        targetIdPattern, // replacement pattern for the target element's ID, e.g. 'PopAroundTarget_$1'
                        targetClassNameBefore, // the class name the target element will have before the event fires
                        targetClassNameAfter // the class name the target element should have after the event fires
                    ) {
    if (!document.getElementsByTagName) return false;
    var triggerElements = getElementsByClassName(triggerTagName, triggerClassName);
    for (var i in triggerElements) {
        try {
            // Find corresponding element 
            var triggerElement = triggerElements[i];
            var targetElementId = triggerElement.id.replace(new RegExp(triggerIdPattern), targetIdPattern);
            // Add event handler
            // HACK: only way I've figured out to pass the information needed for when the event fires, is to build this whole command in a string and then eval it. Got to be a more object-oriented, less script-y way
            f = "triggerElement[triggerEvent] = function() { changeClassName('{0}', '{1}', '{2}');}";
            f = stringFormat(f, [ targetElementId, targetClassNameBefore, targetClassNameAfter ] );
            eval(f);
        }
        catch (e) {
            // ignore elements we can't find/hookup
        }
    }
} 

// makeClickableByProxy
//
// Makes an entire set of divs clickable, taking the destination from an HTML link inside each div
//
function makeClickableByProxy(triggerTagName, triggerClassName, targetLinkClassName)
{
    if (!document.getElementsByTagName) return false;
    var triggerElements = getElementsByClassName(triggerTagName, triggerClassName);
    for (var i in triggerElements) {
        // Find corresponding element 
        var triggerElement = triggerElements[i]
        f = "triggerElement.onclick = function() { clickInside(this,'{0}');}"
        f = stringFormat(f, [ targetLinkClassName ] );
        eval(f)
    }
}

// clickInside
//
// Finds a link in the trigger div with the named class, and navigates to its href location
// Use as the onclick handler function for a div
function clickInside(triggerElement, targetLinkClassName) {
    if (typeof(triggerElement) != 'object') { triggerElement = document.getElementById(triggerElement) } // Accept ID of element (string) or the element itself
    var links = triggerElement.getElementsByTagName('a'); 
    // Find a with class=targetLinkClassName
    for (var i=0; i<links.length; i++) {
        if (links[i].className && links[i].className.indexOf(targetLinkClassName)>-1) {
            // Act as if the link itself had been clicked
            // Note: If the URL is external (different site), IE7 will load it in a new browser window
             window.location = links[i].href;
        } 
    }  
}

// clearOnFocus
//
// Clears an input when it receives focus
//
function clearOnFocus(targetClassName)
{
    if (!document.getElementsByTagName) return false;
    var targetElements = getElementsByClassName('input', targetClassName);
    for (var i in targetElements) {
        targetElements[i].onfocus = function() { this.value='' }
    }
}
    

function newImage(arg) {
  if (document.images) {
    rslt = new Image();
    rslt.src = arg;
    return rslt;
  }
}



/************************************** APPLICATION-SPECIFIC FUNCTIONS */


function wireupTripleStandardsSelector() {
    // Select one at random
    selectTripleStandardsIndex(Math.floor(Math.random()*3)+1);
    // Wire up behavior
    for (var i=1; i<=3; i++) {
        var Selector = document.getElementById("TripleStandardsSelector_" + i);
        f = "Selector.onmouseover = function() { selectTripleStandardsIndex(" + i + ");} ; ";
        eval(f);
    }
}

function selectTripleStandardsIndex(index) {
    for (var i=1; i<=3; i++) {
        var Selector = document.getElementById("TripleStandardsSelector_" + i);
        var Banner = document.getElementById("TripleStandardsBanner_" + i);
        // Make sure images are preloaded
        preloadedImage = newImage('../images/' + i + '.off.gif');
        preloadedImage = newImage('../images/' + i + '.on.gif');
        // Turn on or off 
        if (i==index) {
            //  Turn on
            changeClassName(Selector,"Off","On");
            changeClassName(Banner,"Off","On");
        }
        else
        {
            //  Turn off
            changeClassName(Selector,"On","Off");
            changeClassName(Banner,"On","Off");
        }
    }
}


function wireupCreditBehavior()
{
	if (!document.getElementById) return false;
	mainBottomDiv= document.getElementById('MainBottom');
	mainBottomDiv.onmouseover = function() { document.getElementById('Credit').className='Hover'; };
	mainBottomDiv.onmouseout = function() { document.getElementById('Credit').className=''; };
	mainBottomDiv.onclick = function() { window.open('http://www.caudillweb.com', 'caudill'); };
	// preload image
	preloadedImage = newImage('../images/cwt.on.gif')
}


checkToggle = function(
                checked, // to check or not
                targetElement // the id of the div containing checkboxes to flip
                )
{
    if (typeof(targetElement) != 'object') { targetElement = document.getElementById(targetElement) } // Accept ID of element (string) or the element itself
    if (!targetElement.getElementsByTagName) return false;
    var targetElements = targetElement.getElementsByTagName('input');
    for (var i in targetElements) {
        if (targetElements[i].disabled == false) targetElements[i].checked = checked;
    }
}

// wireUpCheckToggle 
//
wireUpCheckToggle = function(
                        triggerClassName, // class of the trigger elements (e.g. 'PopAroundTrigger')
                        triggerIdPattern, // regex pattern matching the trigger element's ID, e.g. 'PopAroundTrigger_(\d*)' 
                        targetIdPattern // replacement pattern for the target element's ID, e.g. 'PopAroundTarget_$1'
                    ) 
{
    if (!document.getElementsByTagName) return false;
    var triggerElements = getElementsByClassName('input', triggerClassName);
    var arrIndex;
    for (arrIndex = 0; arrIndex < triggerElements.length; arrIndex++) {
            // Find corresponding element 
            var triggerElement = triggerElements[arrIndex];
            var targetElementId = triggerElement.id.replace(new RegExp(triggerIdPattern), targetIdPattern);
            // Create event handler
            var f = "checkToggle(this.checked, '" + targetElementId + "'); ";
            // Store the event handler with the element itself
            eval("triggerElement.onclick = function() { "  + f  + " }" );
           // Set initial state according to current status
           checkToggle(triggerElement.checked, targetElementId); 
    }
} 


/************************************** BEHAVIORS FOR THIS APPLICATION */

function addBehaviors() {
    wireupCreditBehavior();
    wireUpCheckToggle('_CheckAllTrigger', 'CheckAllTrigger_(.*)', 'CheckAllTarget_$1');
    makeClickableByProxy('div','ClickByProxy', 'ClickTarget');
}

addLoadEvent(addBehaviors);  






    