/** Common helper functions **/


function getBaseURL() {
    var baseURL = document.location.href;
    var xend = baseURL.lastIndexOf("/") + 1;
    baseURL = baseURL.substring(0, xend);
    return baseURL;
}

/*
 * Cookie functions
 * From: http://www.quirksmode.org/js/cookies.html
 */

function createCookie(name,value,days) {
    if (days) {
        var date = new Date();
        date.setTime(date.getTime()+(days*24*60*60*1000));
        var expires = "; expires="+date.toGMTString();
    }
    else var expires = "";
    document.cookie = name+"="+value+expires+"; path=/";
}

function readCookie(name) {
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');
    for(var i=0;i < ca.length;i++) {
        var c = ca[i];
        while (c.charAt(0)==' ') c = c.substring(1,c.length);
        if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
    }
    return null;
}

function eraseCookie(name) {
    createCookie(name,"",-1);
}

/** See documentation below
 * From: http://aspn.activestate.com/ASPN/Cookbook/PHP/Recipe/414334
 */ 
function js_array_to_php_array (a)
// This converts a javascript array to a string in PHP serialized format.
// This is useful for passing arrays to PHP. On the PHP side you can 
// unserialize this string from a cookie or request variable. For example,
// assuming you used javascript to set a cookie called "php_array"
// to the value of a javascript array then you can restore the cookie 
// from PHP like this:
//    <?php
//    session_start();
//    $my_array = unserialize(urldecode(stripslashes($_COOKIE['php_array'])));
//    print_r ($my_array);
//    ?>
// This automatically converts both keys and values to strings.
// The return string is not URL escaped, so you must call the
// Javascript "escape()" function before you pass this string to PHP.
{
    var a_php = "";
    var total = 0;
    for (var key in a)
    {
        ++ total;
        a_php = a_php + "s:" +
                String(key).length + ":\"" + String(key) + "\";s:" +
                String(a[key]).length + ":\"" + String(a[key]) + "\";";
    }
    a_php = "a:" + total + ":{" + a_php + "}";
    return escape(a_php);
}

/**
 * Opens our popup. Returns the new window
 * Export is true when the window is used for exporting
 */
function openPopup(exportData) {
 return window.open("field_match.php" + (exportData ? "?_export_flag=1" : ""),"popUpWindow","menubar=1,scrollbars=1,height=700,width=400");
}

//checks that all the characters in a string are numerals
//thus it only checks for integers
function checkNumber(strnum) {
       for (i = 0; i < strnum.length; i++) {
        ch = strnum.substring(i, i+1);
        if (ch < "0" || ch > "9")
          {
          return false;
          }
    }
    return true;
}

//Ensures that a string from a form field is an integer
//minimum: optional, the minimum allowable number (inclusive)
//maximum: optional, the maximum allowable number (inclusive)
//please specify both min and max if you want to specify one.
function checkLong(strnum,minimum,maximum) {
    var good=true;
    if (strnum.length>0) {
        good=good && checkNumber(strnum);
        if (good) {
            var number=new Number(strnum);
            mini=new Number(minimum); maxi=new Number(maximum);
            if(minimum && mini>number) good=false;
            if(maximum && maxi<number) good=false;
        }
        if (!good) {
        var message="Field must be a positive whole number";
        if (minimum || maximum) message+= " between " + minimum + " and " + maximum;
        message+=".";
        alert(message);
        window.document[frm][fld].focus();
        }
    }
    return good;
}

 
/** For sorting arrays of numbers **/
function sortNumber(a,b)
{
    return a - b;
}

/** Binary search in a sorted array
 * Adapted From http://en.wikipedia.org/wiki/Binary_search
 * returns index of num if num is in array arr
 * else if num would go in index ind, returns: (-1*ind) - 1
 **/

function binarySearch(arr,num) {
    function bsHelp(arr,num,left,right) {
        if(right < left) {
            return (-1 * left) - 1;
        }
        else {
            var mid = Math.floor((right - left) / 2) + left;
            if (num > arr[mid]) {return bsHelp(arr,num,mid+1,right);}
            else if (num < arr[mid]) {return bsHelp(arr,num,left,mid-1);}
            else {return mid;}
        }
    }

    return bsHelp(arr,num,0,arr.length-1);
}
/** Binary search with guarantee we get the minimum index **/
function binarySearchMin(arr,num) {
    var ind=binarySearch(arr,num);
    if (ind<0) return ind;
    while(ind>=0 && arr[ind]==num) ind--;
    return(ind+1);
}

/** Create a DOM image element **/
function createImageNode(isrc) {
  var img = document.createElement("img");
  img.src=isrc;
  return(img);
}

function selectedValue(selObj) {
    return(selObj.options[selObj.selectedIndex].value);
}

/** strict is optional **/
function setSelected(selObj,value,strict) {
    var found=false;
    for (var i=0;i<selObj.length;i++) {
        if(selObj.options[i].value == value) {
            found=true;
            selObj.selectedIndex=i;
        }
    }
    if (strict && !found) alert("Couldn't find " + value + " for " + selObj.name + ".");
}


/**
 * Returns the instance of our class.  Won't work
 * for objects that are extensions of DOM nodes, but
 * will work for most of our purposes 
 * 
 * Uses the fact that I define my constructs with the convention:
 * function className(<params>) {}
 */
 function instanceOf(instance) {
    var t = typeof instance;
    if (t != 'object') return false;
    else {
        var constr = instance.constructor.toString();
        if (constr) {
            var pos1 = constr.indexOf(" "); 
            var pos2 = constr.indexOf("("); //)
            if (pos1>-1 && pos2>-1) {
                return constr.substring(pos1+1,pos2);
            }
            else alert("Error in instanceOf:" + constr.substring(0,50));
        }
        else alert("Error in instanceOf:" + instance);
    }
 }

/**Drop punction and extra spaces **/
/** TODO: fix**/
function cleanString(str) {
    var regEx = new RegExp ("  ", "gi") ;
    str = str.replace(regEx, " ");
    regEx = new RegExp ("\.", "gi") ;
    str = str.replace(regEx, "");
    return str;
}


/**
 * Get the height and width of the window
 */
 function getWindowDimensions() {
    var totalHeight; var totalWidth;
    if (typeof window.innerHeight == 'undefined') {
        /** For Internet Explorer **/
        if (typeof document.documentElement.clientHeight == 'undefined') {
            /** Old IE **/
            totalHeight=document.body.clientHeight;
            totalWidth=document.body.clientWidth;
        } else {
            /** New IE **/
            totalHeight=document.documentElement.offsetHeight;
            totalWidth=document.documentElement.offsetWidth;
        }
    } else {
        totalHeight=window.innerHeight;
        totalWidth=window.innerWidth;
    }
    var retv=new Array(2);
    retv[0]=totalWidth;
    retv[1]=totalHeight;
    return retv;
 }

/*
 * For the instructions page: creates outline at the top of the page
 * Recursive function:
 * fromEl is the element we're copying from
 * toEl is the element to copy to
 * allowText is a flag (0 or 1) to indicate whether we're in a title
 * and to allow text
 **/
function createOutline(fromEl,toEl,allowText) {
  for(var i = 0; i<fromEl.childNodes.length; i++) {
    var child=fromEl.childNodes[i];
    if (child.nodeType==3 && allowText==1) {
        if (child.nodeValue.length>1) {
            var newT=document.createTextNode(child.nodeValue);
            var newA=document.createElement("A");
            newA.href="#" + child.nodeValue;
            newA.appendChild(newT);
            var forOld=newT.cloneNode(false);
            var forOldA=document.createElement("A");
            forOldA.name=child.nodeValue;
            forOldA.appendChild(forOld);
            
            toEl.appendChild(newA);
            fromEl.replaceChild(forOldA,child);
        }
    } else if (child.tagName=="LI" && child.className.indexOf("Title") > -1) {
        var newD=document.createElement(child.tagName);
        newD.className="instrOutline";
        createOutline(child,newD,1);
        if (newD.hasChildNodes) toEl.appendChild(newD);
    } else if (child.tagName=="OL" || child.tagName=="UL" || (child.tagName=="LI" && allowText==1)) {
        var newL=document.createElement(child.tagName);
        newL.className=child.className;
        createOutline(child,newL,allowText);
        if (newL.hasChildNodes) toEl.appendChild(newL);
    }
  }
}

/*
 * For the front page.  Adjusts the image size proportionally
 * Based on the desired
 */
function adjustImageSize(img,widthPct) {
    var dims=getWindowDimensions();
    var windowWidth=dims[0];
    var oldWidth= img.offsetWidth;
    var oldHeight= img.offsetHeight;
    var newWidth=Math.round(widthPct * windowWidth);
    if (newWidth<oldWidth) {
        img.style.width=  newWidth + "px";
        img.style.height= Math.round(oldHeight * (newWidth / oldWidth)) + "px";
    }
}

