/**
 * Site Wide Javascript Functions
*/

/**
 * This function will create a email address that is robot crawler free
 */ 
function jb_setMail(id, name, gloablDomain, domainName, changeHTML){
    var aTag = document.getElementById(id);
    var emAd = name+"@"+domainName+"."+gloablDomain
    aTag.innerHTML = (changeHTML) ? changeHTML : emAd;
    aTag.href = "mailto:"+emAd;
    return false;
}

/**
 * This array is here to hold all the active animation_slide_y targets.
 * The target is the pixle value as a integer. 
 */ 
var animation_slide_y_targets = new Array();
/**
 * This array holds all the setInterval IDs so that they can be cleared based on the elements ID
 */ 
var animation_slide_y_intervals = new Array();
/**
 * This function actuly starts the div slide animation.
 * It clears any existing Intervals for this elements ID. 
 * Then it invokes the {@link animation_slide_y_step()} function as a Interval.
 */ 
function animation_slide_y($element, $target){
    animation_slide_y_targets[$element.id] = $target;
    window.clearInterval(animation_slide_y_intervals[$element.id]);
    animation_slide_y_intervals[$element.id] == false;
    animation_slide_y_intervals[$element.id] = setInterval(function(){ animation_slide_y_step($element); }, 50);
}
/**
 * This function preforms each step as a Interval set by {@link animation_slide_y()}.
 * It only stops once its reached its goal (Stored in animation_slide_y_targets[$element.id]) .
 * Once its complete will either become display none, or height 100%.
 * In order to deal with the height 100% in IE some elements will need to be places in table cells.
 */ 
function animation_slide_y_step($element){
    var curY = ($element.style.top.slice(0,-2))*1;
    var diff = animation_slide_y_targets[$element.id]-curY;
    var step = Math.round((diff)/5);
    if(step != 0 ){
        $element.style.top = (curY+step)+'px';
    }else{
        $element.style.top = animation_slide_y_targets[$element.id]+'px';
        window.clearInterval(animation_slide_y_intervals[$element.id]);
        animation_slide_y_intervals[$element.id] = false;
    }
}

/**
 * This function loading in a cookie from the uses system 
 * @params name of the cookie you are trying to retrieve
 */
function get_cookie(cookie_name){
    var results = document.cookie.match (cookie_name + '=(.*?)(;|$)');
    if (results){
        return(unescape(results[1]));
    }else{
        return null;
    }
}


/**
 * This function sets a cookie to the uses system
 * @parmas string Name of the cookie being set
 * @parmas string Value of the cookie being set
 * @parmas string Time to live in seconds (if not set it will be one year.
 */
function set_cookie(name, value, expires){
    var cookie_string = name + "=" + escape(value);

    var today = new Date();
    today.setTime(today.getTime());
    if (!expires){    var expires = 365;   }
    expires = expires * 60 * 60 * 24;

    var expires_date = new Date( today.getTime() + (expires) );
    cookie_string += "; expires=" + expires_date.toGMTString();

    cookie_string += "; path="+ '/';
    if(domain) cookie_string += "; domain=" + domain;

    document.cookie = cookie_string;

}

/**
 * This function removes a cookie from the users computer
 * @params string Name of the cookie to delete
 */
function delete_cookie(cookie_name){
    var cookie_date = new Date ();  // current date & time
    cookie_date.setTime (cookie_date.getTime() - 1);
    document.cookie = cookie_name + "=; expires=Thu, 01-Jan-1970 00:00:01 GMT";
    return false;
}

/**
 * This function will switch the visable panel, as well as the button, if one is selected. 
 * All buttons must be:
 * - in the same parent
 * - a A tag
 * All panels must be:
 * - in the same parent
 * - a DIV tag 
 * 
 * @param HTMLElement The panel to display
 * @param HTMLElement The button that is related to this panel
 * @return DOM element
 */
function switch_panel($active_panel, $button){
    var $pannel_siblings = $active_panel.parentNode.childNodes;
    var length = $pannel_siblings.length;
    for(var i=0;i<length;i++){
        if($pannel_siblings[i].tagName == 'DIV'){
            $pannel_siblings[i].style.display = 'none';
        }
    }
    $active_panel.style.display = 'block';

    var $button_siblings = $button.parentNode.childNodes;
    var length = $button_siblings.length;
    for(var i=0;i<length;i++){
        if($button_siblings[i].tagName == 'A'){
            $button_siblings[i].className = 'tab_inactive';
        }
    }
    $button.className = 'tab_active';            
}

/**
 * This returns a DOM element from a string or 
 * an array of elements if its an array is passed
 *
 * @param {string||array} element The ID of element to create
 * @return DOM element
 */
function $(element) {
  if (arguments.length > 1) {
    for (var i = 0, elements = [], length = arguments.length; i < length; i++)
      elements.push($(arguments[i]));
    return elements;
  }
  if (typeof element == 'string')
    element = document.getElementById(element);
  return element;
}


/**
 * This function returns true if the browser is IE
 */ 
function isIE(){
    if(navigator.appName.indexOf("Internet Explorer")!=-1){
        return true;
    }else{
        return false;
    }
}


/**
 * This ugly verstion of getElementsByName is here so that the function will work corectly in IE.
 * @params {string} tag It needs a tag to search for the items name
 * @params {string} name The name to look for
 */ 
function ugly_getElementsByName(tags, name) {
     var arr = new Array();
     for(t=0;t<tags.length;t++){
         var elem = document.getElementsByTagName(tags[t]);
         for(i = 0; i < elem.length; i++) {
              att = elem[i].getAttribute("name");
              if(att == name) {
                   arr.push(elem[i]);
              }
         }
     }
     return arr;
}

/**
 * This returns an array from document.getElementsByName 
 * @param {$name} The name to look for 
 */
function $_($name){
    var item_ar = document.getElementsByName($name);
    return item_ar;
}

/**
 * This returns the first child of a DOM element that has a specific name 
 * @param {$element} element to check the children of
 * @param {$name} The name to look for 
 * @return DOM element
 */
function $_child($element, $name){
    var leng = $element.childNodes.length;
    for(var i =0; i < leng; i++){
        if($element.childNodes[i].name == $name){
            var child = $element.childNodes[i];
            break;
        }
    }
    return child;
}

/**
 * This returns an array of DOM elements that are conainted in one Item and have a specific name 
 * @param {$element} element to check the children of
 * @param {$name} The name to look for 
 * @return an array of DOM element
 */
function $_children($element, $name){
    var children_ar = new Array();
    var leng = $element.childNodes.length;
    for(var i =0; i < leng; i++){
        if($element.childNodes[i].name == $name){ 
            children_ar.push($element.childNodes[i]);
        }
    }
    return children_ar;
}

/**
 * This forses a stage element to render
 *
 * @param {string} $element The ID of element to create
 */
function forceRerendering($element) {
    var n = document.createTextNode(' ');
    $element.appendChild(n);
    $element.removeChild(n);
};

/**
 * This removes a item from the DOM
 */
function remove_element($element){
    $element.parentNode.removeChild($element);
}

/**
 * This switches the display propertie for a item
 * @param object the HTMLentitie to toggle
 */
function toggle_display($item, $this_item, $display_type){
    if( ($item.style.display == 'none' && !$display_type)        || $display_type == 'block' ){
        if($this_item) $this_item.className = "tree_opened";
        animation_accordion($item, 'open');
    }else if( ($item.style.display == 'block' && !$display_type) || $display_type == 'none' ){
        if($this_item) $this_item.className = "tree_closed";    
        animation_accordion($item, 'close');
    }
}
/**
 * This array is here to hold all the active animation_accordion targets.
 * The target is the pixle value as a integer. 
 */ 
var animation_accordion_targets = new Array();
/**
 * This array holds all the setInterval IDs so that they can be cleared based on the elements ID
 */ 
var animation_accordion_intervals = new Array();
/**
 * This function actuly starts the accordion animation.
 * First it preps the DIV and sets some nessasary CSS styles.
 * Next it clears any existing Intervals for this elements ID. 
 * Last it invokes the {@link animation_accordion_step()} function as a Interval.
 * To get the padding to scale some of the scaling div have no other settings but be a container. 
 */ 
function animation_accordion($element, $target){
    if(!animation_accordion_intervals[$element.id]){
        if($element.style.overflow != 'hidden') $element.style.overflow = 'hidden';
        if($element.style.display == 'none'){
            $element.style.height = '0px';
        }else{
            $element.style.height = $element.scrollHeight+'px';
        }
    }
    if($target == 'close'){
        animation_accordion_targets[$element.id] = 0;
    }else{
        $element.style.display = "block";
        animation_accordion_targets[$element.id] = $element.scrollHeight;
    }
    window.clearInterval(animation_accordion_intervals[$element.id]);
    animation_accordion_intervals[$element.id] == false;
    animation_accordion_intervals[$element.id] = setInterval(function(){ animation_accordion_step($element); }, 40);
}
/**
 * This function preforms each step as a Interval set by {@link animation_accordion()}.
 * It only stops once its reached its goal (Stored in animation_accordion_targets[$element.id]) .
 * Once its complete will either become display none, or height 100%.
 * In order to deal with the height 100% in IE some elements will need to be places in table cells.
 */ 
function animation_accordion_step($element){
    var curHeight = ($element.style.height.slice(0,-2))*1;
    var diff = animation_accordion_targets[$element.id]-curHeight;
    var step = Math.round((diff)/4);
    if(step != 0 ){
        $element.style.height = (curHeight+step)+'px';
    }else{
        $element.style.height = animation_accordion_targets[$element.id]+'px';
        window.clearInterval(animation_accordion_intervals[$element.id]);
        animation_accordion_intervals[$element.id] = false;
        if($element.style.height == '0px'){
            $element.style.display = "none";
        }else{
            $element.style.height = '100%';
        }
    }
}


/**
 * This switches the display propertie alll items named toggle to block
 */
function toggle_show_all($name){
    if(!$name) $name = 'toggle';
    toggle_all('block', $name);
}

/**
 * This switches the display propertie alll items named toggle to none
 */
function toggle_hide_all($name){
    if(!$name) $name = 'toggle';
    toggle_all('none', $name);
}

/**
 * Used for the two functions aboved
 */
function toggle_all($display_type, $name){
    if ( isIE() ){
       var list_elements         = ugly_getElementsByName(['div','blockquote'], $name);
       var list_elements_buttons = ugly_getElementsByName(['a','b'], $name+'_button');
    }else{
       var list_elements         = document.getElementsByName($name);
       var list_elements_buttons = document.getElementsByName($name+'_button');
    }
    for(var i = 0; i < list_elements.length; i++){
        toggle_display(list_elements[i], list_elements_buttons[i], $display_type)
    }
}

/**
 * Change the state of all checkboxes in a form, or all checkboxs in a form with the same name.
  *
 * @param string The state to make the checkbox
 * @param HTMLElement The form that is being processsed
 * @param string The optional name of the checkboxes to check/uncheck
 */
function massCheckBoxState($state, $form, $name){
    for(var i=0; i<$form.elements.length; i++){
        if($form.elements[i].type == 'checkbox'){
            if($name){
                var $thisName = $form.elements[i].name;
                if($thisName.match($name)) $form.elements[i].checked = $state;
            }else{
                $form.elements[i].checked = $state;
            }
        }
    }
}
/**
 * This will submit the form
  *
 * @param {$item} the select item
 * @param {$message} the message to ask
 * @param {$form} the form to submit
 */
function select_submit($item,$message,$form){
    if(!$form) $form = $($item.parentNode.id);
    var answer = confirm($message);
    if (answer){
       if($form.onsubmit){
           $form.onsubmit()
       }else{
           $form.submit();
       }
    }else{
        return false;
    }    
}

/**
 * This ask for confimatino before sending in the form
 * @param {$form} the form to submit
 * @param {$message} the message to ask
 */
 function confirm_submit($form, $message){
    var answer = confirm($message);
    if (answer){
       $form.submit();
       return true;
    }else{
        return false;
    }    
}

/**
 * This will replace the form with a please wait message while files upload
 * @param HTMLElement the form to submit and hide
 * @param HTMLElement the element that will be shown to replace the form 
 * @param string the optional message to display
 */
function waiting_for_submit($form, $element, $message){
    if(!$message) $message = '<div style="text-align:center; margin:auto;" class="alert">Please wait while your submition is processsed</div>';
    $element.innerHTML = $message;
    var $newHeight = $form.scrollHeight;
    var $newWidth  = $form.scrollWidth;
    $form.style.overflow = 'hidden';
    $form.style.height = '0px';
    $element.style.display = 'block';
    $element.style.height = $newHeight+'px';
    $element.style.width = $newWidth+'px';
}

/**
 * This will visit the URL if the user acepts the alert
 *
 * @param {url} the location to go if yes
 * @param {message} the message to ask
 */
function confirmation(url, message) {
	var answer = confirm(message)
    if (answer){
       window.location = url;
    }
}

/**
 * This will set http:// into a url input field if its not alreay set
 * @param {$field} The field to test
 */
function prep_field_url($field) {
	if(!$field.value) $field.value = 'http://';
}


/**
 * AJAX Stuff
 */

var JSON_timeout = new Array();
function JSON() {
    var xmlhttp;    
}
JSON.prototype.init = function () {
    this.xmlhttp=false;
    /*@cc_on @*/
    /*@if (@_jscript_version >= 5)
    try { this.xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");} catch (e) { try { this.xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } catch (E) { this.xmlhttp = false;}}
    @end @*/
    if (!this.xmlhttp && typeof XMLHttpRequest!='undefined') {try {this.xmlhttp = new XMLHttpRequest();} catch (e) {this.xmlhttp=false;}}
    if (!this.xmlhttp && window.createRequest) {try {this.xmlhttp = window.createRequest();} catch (e) {this.xmlhttp=false;}}
}
JSON.prototype.request = function ($data_type,$params_z,callback,section_type) {
    this.init();
    var string="";
    params_length=$params_z.length;
    string = "type="+$data_type+"&params="+JSON_parser.encode($params_z);
    var tempxmlhttp=this.xmlhttp;
    tempxmlhttp.open("POST","/api.php");
    tempxmlhttp.setRequestHeader('Content-Type', "application/x-www-form-urlencoded");
    tempxmlhttp.setRequestHeader("Content-length", string.length);
    tempxmlhttp.onreadystatechange=function() {if (tempxmlhttp.readyState==4) {if (tempxmlhttp.status!=404) {var local=JSON_parser.decode(tempxmlhttp.responseText);callback(local);} else {alert("JSON Call Failed!");}}}
    if (JSON_timeout[$data_type]) clearTimeout(JSON_timeout[$data_type]);
    var timeoutFunc = function() { tempxmlhttp.send(string); }
    JSON_timeout[$data_type]=setTimeout(timeoutFunc,200);
}

JSON_parser = new function(){
    var useHasOwn = {}.hasOwnProperty ? true : false;
    
    var pad = function(n) {
        return n < 10 ? '0' + n : n;
    };
    
    var m = {
        '\b': '\\b',
        '\t': '\\t',
        '\n': '\\n',
        '\f': '\\f',
        '\r': '\\r',
        '"' : '\\"',
        '\\': '\\\\',
        '&' : '%26'
    };

    var encodeString = function(s){
        if (/[^\w]/.test(s)) {
            return '"' + s.replace(/([^\w])/g, function(a, b) {
                var c = m[b];
                if(c) return c;
                c = b.charCodeAt();
                return '\\u00'+Math.floor(c / 16).toString(16)+(c % 16).toString(16);
            }) + '"';
        }
        return '"' + s + '"';
    };
    
    var encodeArray = function(o){
        var a = ['['], b, i, l = o.length, v;
            for (i = 0; i < l; i += 1) {
                v = o[i];
                switch (typeof v) {
                    case 'undefined':
                    case 'function':
                    case 'unknown':
                        break;
                    default:
                        if (b) {
                            a.push(',');
                        }
                        a.push(v === null ? "null" : JSON_parser.encode(v));
                        b = true;
                }
            }
            a.push(']');
            return a.join('');
    };
    
    var encodeDate = function(o){
        return '"' + o.getFullYear() + '-' +
                pad(o.getMonth() + 1) + '-' +
                pad(o.getDate()) + 'T' +
                pad(o.getHours()) + ':' +
                pad(o.getMinutes()) + ':' +
                pad(o.getSeconds()) + '"';
    };
    
    /**
     * Encodes an Object, Array or other value
     * @param {Mixed} o The variable to encode
     * @return {String} The JSON string
     */
    this.encode = function(o){
        if(typeof o == 'undefined' || o === null){
            return 'null';
        }else if(o instanceof Array){
            return encodeArray(o);
        }else if(o instanceof Date){
            return encodeDate(o);
        }else if(typeof o == 'string'){
            return encodeString(o);
        }else if(typeof o == 'number'){
            return isFinite(o) ? String(o) : "null";
        }else if(typeof o == 'boolean'){
            return String(o);
        }else {
            var a = ['{'], b, i, v;
            for (var i in o) {
                if(!useHasOwn || o.hasOwnProperty(i)) {
                    v = o[i];
                    switch (typeof v) {
                    case 'undefined':
                    case 'function':
                    case 'unknown':
                        break;
                    default:
                        if(b){
                            a.push(',');
                        }
                        a.push(this.encode(i), ':',
                                v === null ? "null" : this.encode(v));
                        b = true;
                    }
                }
            }
            a.push('}');
            return a.join('');
        }
    };
    
    /**
     * Decodes (parses) a JSON string to an object.
     * @param {String} json The JSON string
     * @return {Object} The resulting object
     */
    this.decode = function(json){
        var result = json;
        if (json.substr(0,9)=="while(1);") json = json.substring(9);
        var reg_json = /\<br \/\>([\w\W]*)\<br \/\>/;
        if(result.match(reg_json)){
            alert("JSON Repsonse error: "+RegExp.$1);
        }else{
            return new Function("return "+json)();
        }
    };
}(); 

/**
 * This function will handle any AJAX errors
 * If there is NO error is responce true 
 */ 
function error_check($errorCode,$errorString){
    if($errorCode){
        switch($errorCode){
            default:
                alert('You have encountered Error #'+$errorCode+': \n'+$errorString);
            break;
        
        }
        return false;
    }else{
        return true;
    }
}

