/**
 *  File: strings.js
 *  Purpose: Methods for string manipulation such as validators, encoders
 *  Revisions: 2005Aug09 - initial rev
 *
 **/

var patternSimpleEmail	= /(.+)\@(.+)\.(.+)$/;
var patternEmail  = /^([\w\_\.\-\+])+\@(([\w\-])+\.)+([\w\.])+$/; // allow (+) in student email
//var patternEmail  = /^([\w\_\.\-])+\@(([\w\-])+\.)+([\w\.])+$/; // do not allow (+)
var patternProfessorEmail  = /^([\w\_\.\-\+])+\@(([\w\-])+\.)+([\w\.])+$/;  // allow (+) in prof email
//var patternProfessorEmail  = /^([\w\_\.\-])+\@(([\w\-])+\.)+([\w\.])+$/;  // do not allow (+)
var patternAlpha  = /^([a-zA-Z])+$/;
var patternNumeric  = /^([\d])+$/; // alternative to isNaN
var patternInteger  = /^(-?\d+)$/; // alternative to isNaN
var patternFloat  = /^(((-)?\d+(\.\d*)?)|((-)?(\d*\.)?\d+))$/; // 1. or 1 or .8
var patternAlphaNumeric  = /^([a-zA-Z0-9])+$/;
var patternAlphaSpace  = /^([a-zA-Z\s])+$/;
var patternAlphaExtra  = /^([\w\s\'\.\-])+$/;
var patternAlphaNumericExtra  = /^([\w\s\'\.\-])+$/; // \w=a-zA-Z0-9_, \s=space
var patternAlphaNumericExtraFull  = /^([\w\s\,\'\.\-\?\!\@\#\$\%\^\&\*\(\)\+\=\[\]\{\}\|\\\/\"\:])+$/; // \w=a-zA-Z0-9_, \s=space
var patternAlphaNumericExtraFull_NoDoubleQuotes  = /^([\w\s\,\'\.\-\?\!\@\#\$\%\^\&\*\(\)\+\=\[\]\{\}\|\\\/\:])+$/; // \w=a-zA-Z0-9_, \s=space
var patternAngleBracket  = /.?[<>]+.?/; // anything 0+, < or > 1+, anything 0+
var MSG_VALID_CHARS_ALPHA_SPACE = "Valid characters include a-z, A-Z, and spaces.";
var MSG_VALID_CHARS_ALPHANUMERIC_EXTRA = "Valid characters include a-z, A-Z, 0-9, underscores, spaces, apostrophes, periods, and dashes.";
var MSG_VALID_CHARS_ALPHANUMERIC_EXTRA_FULL = "Valid characters include a-z, A-Z, 0-9, _, spaces, commas, \', ., -, ?, !, @, #, $, %, ^, &, *, (, ), +, =, [, ], {, }, |, \\, /, \", :  .";

// /^[\w-]+(?:\.[\w-]+)*@(?:[\w-]+\.)+[a-zA-Z]{2,7}$/
//var patternPhone = ((\(\d{3}\) ?)|(\d{3}(-|\.| )?))\d{3}(-|.)?\d{4}( x\d{1,5})?;
//var patternPhone = /^\(\d{3}\) \d{3}-\d{4}$/; // (ddd) ddd-dddd

// replace the + ' " that escape() misses
function urlEncode( str ) {
    return escape(str).replace(/\+/g, '%2B').replace(/\"/g,'%22').replace(/\'/g, '%27');
}

function hasAngleBrackets( value ) {
    return patternAngleBracket.test( value);
}

function isEmailFormat( email ) {
    return patternEmail.test( email.trim() );
}

function isSimpleEmailFormat( email ) {	
	return patternSimpleEmail.test ( email.trim() );
}

function isProfessorEmailFormat( email ) {
    return patternProfessorEmail.test( email.trim() );
}

function isAlphaValue( value ) {
    return patternAlpha.test(value.trim());
}

function isNumericValue( value ) {
    return patternNumeric.test(value.trim());
}

function isFloatValue( value ) {
    return patternFloat.test(value.trim());
}

function isIntegerValue( value ) {
    return patternInteger.test(value.trim());
}

function isAlphaNumericValue( value ) {
    return patternAlphaNumeric.test(value.trim());
}

function isAlphaSpaceValue( value ) {
    return patternAlphaSpace.test(value.trim());
}

function isAlphaExtraValue( value ) {
    return patternAlphaExtra.test(value.trim());
}

function isAlphaNumericExtraValue( value ) {
    return patternAlphaNumericExtra.test(value.trim());
}

function isAlphaNumericExtraFullValue( value ) {
    return patternAlphaNumericExtraFull.test(value.trim());
}

function isAlphaNumericExtraFullValue_NoDoubleQuotes( value ) {
    return patternAlphaNumericExtraFull_NoDoubleQuotes.test(value.trim());
}
/*
function isPhoneFormat( phone ) {
    return patternPhone.test( phone );
}
*/

String.prototype.trim = stringTrim;
// [ \f\n\r\t\v] for lead and trailing
function stringTrim() {
   return this.replace(/^\s*|\s*$/g,"");
}

/**
 * Used by Course Outline for maintaining your place
 */
function jumpToAnchor( anchorName ) {
    var currentLocation = window.location.toString();
    currentLocation = currentLocation.split("#")[0];
    window.location = currentLocation + "#" + anchorName;
}


/*
* Used for textarea character counter, see code for example
*/
function countCharacters(textArea, counterField, maxLength, defaultClass, errorClass)
{
    if (textArea !=null && textArea.value != null)
    {
        var len = textAreaLength(textArea);
/*        var offset = Math.abs(len - textArea.value.length);*/
        if (len > maxLength) {
            counterField.className = errorClass;
        } else {
            counterField.className = defaultClass;
        }
        counterField.value = maxLength - len;
/*
        if (len > maxLength)
        {
            counterField.className = errorClass;
        }
        else if (counterField.className == errorClass)
        {
            counterField.className = defaultClass;
        }
        counterField.value = maxLength - len;
*/
    }
}


/**
 * I normally check for object support, but in some Safari cases like getComputedStyle
 * it just flat out lies... 1.3 and possibly above
  */
function isSafari() {
    var bSafari = false;
    var agent=navigator.userAgent.toLowerCase();
    if( agent.indexOf("safari") != -1 ) {
        bSafari = true;
    }
    return bSafari;
}

function isIE() {
    var bIE = false;
    var agent=navigator.userAgent.toLowerCase();
    if( agent.indexOf("msie") != -1 ) {
        bIE = true;
    }
    return bIE;
}

function isMac() {
    var bMac = false;
    var agent=navigator.userAgent.toLowerCase();
    if( agent.indexOf("mac") != -1 ) {
        bMac = true;
    }
    return bMac;
}


/**
 * Debug
 */
function listPositions( obj ) {
    var list = "" +
        "nodeName = " + obj.nodeName + "\n" +
        "parentNode = " + obj.parentNode + "\n" +
        "offsetParent = " + obj.offsetParent + "\n" +
        "\n" +
        "offsetTop = " + obj.offsetTop + "\n" +
        "offsetLeft = " + obj.offsetLeft + "\n" +
        "\n" +
        "clientHeight = " + obj.clientHeight + "\n" +
        "clientWidth = " + obj.clientWidth + "\n" +
        "\n" +
        "offsetHeight = " + obj.offsetHeight + "\n" +
        "offsetWidth = " + obj.offsetWidth + "\n" +
        "\n" +
        "scrollHeight = " + obj.scrollHeight + "\n" +
        "scrollTop = " + obj.scrollTop + "\n" +
        "";
    alert(list);
}

function introspectObj( obj ) {
    if( obj ) {
        var msg = "";
        var count = 0;
        for( i in obj) {
            msg += "\t\t" + i + " = " + obj[i];
            if( ++count % 3 == 0 ) {
                msg += "\n";
            }
        }
        alert(msg);
    }
}

function getCSSProperty( element, propertyName ) {
    var retVal = null;
    if( element.style[propertyName] ) {
        // inline style property
        //alert('style')
        retVal = element.style[propertyName];
    } else if( element.currentStyle ) {
        // external stylesheet for Explorer
        //alert('currentStyle');
        retVal = element.currentStyle[propertyName];
    } else if( document.defaultView && document.defaultView.getComputedStyle ) {
        // external stylesheet for Mozilla and Safari 1.3+
        //alert('getComputedStyle');
        propertyName = propertyName.replace(/([A-Z])/g,"-$1");
        propertyName = propertyName.toLowerCase();
        // safari 1.3 (and above?) lies about getComputedStyle support
        if( !isSafari() ) {
            retVal = document.defaultView.getComputedStyle(element,"").getPropertyValue(propertyName);
        } else {
            var bFoundElement = false;
            var elementId = null;
            if( element.id ) {
                elementId = element.id.toLowerCase();
            }
            //alert(document.styleSheets);
            var allStyleSheets = document.styleSheets;
            if( allStyleSheets ) {
                for( var s=0; s<allStyleSheets.length; s++ ) {
                    if (document.styleSheets[s].cssRules) {
                        //introspectObj(document.styleSheets[1].cssRules[1]);
                        var targetSelector = "*[id\"" + elementId + "\"]";
                        var theseRules = new Array();
                        //alert('cssRules');
                        theseRules = document.styleSheets[s].cssRules;
                        //alert("stylesheet[" + s + "] theseRules.length = " + theseRules.length);

                        for( var r=0; r<theseRules.length; r++ ) {
                        
                        	var sSelectorText = theseRules[r].selectorText;
                        	if (sSelectorText == null) {
                        		continue;
                        	}
                            var fullSselector = theseRules[r].selectorText.toLowerCase();
                            
                            var styleInfo = null;
                            if( theseRules[r].style && theseRules[r].style.cssText ) {
                                styleInfo = theseRules[r].style.cssText;
                            }
                            //alert("selector=" + selector + " , " + selector.indexOf(elementId));

                            // safari format: *[id"paymentcode"] div.content...
                            // #paymentCode, img.popupTopWidthBorder > *[id"paymentcode"]
                            // check for the elementId and the propertyName, then split on the space
                            if( elementId != null && fullSselector.indexOf(elementId) != -1
                                && styleInfo != null && styleInfo.indexOf(propertyName) != -1 ) {
                                var arrSelectors = fullSselector.split(" ");

                                //only process it if it's the only 1, we want to ignore * html IE hacks
                                // multiple listings such #aaa, #paymentCode img.popupTopWidthBorder don't show up?
                                if( arrSelectors.length == 1 && arrSelectors[0].trim() == targetSelector ) {
                                    var arrStyles = styleInfo.split(";");
                                    //alert("stylesheet[" + s + "] \n" + "theseRules[" + r + "] \n" + fullSselector + "\n" + theseRules[r].style.cssText + ", " + arrStyles.length);
                                    for( var j=0; j<arrStyles.length; j++ ) {
                                        var styleFull = arrStyles[j];
                                        var propertyIdx = arrStyles[j].indexOf(propertyName + ":");
                                        if( propertyIdx == 0) {
                                            retVal = styleFull.substring(propertyName.length+1, styleFull.length).trim();
                                        }
                                    }
                                }
                            // cant' stop after finding the first one as that is not the CSS behaviour
                            //if( bFoundElement ) { break; }
                            }
                        }
                    }

                }
            }
        }
    } else {
        // Safari 1.2
    }
    return retVal;
}

function padString( str, count, padChar, bPadTrailing) {

    // return immediately if no padding opportunity
    if( str.length >= count ) {
        return str;
    }

    // enforce string usage otherwise 0 + 1 = 1
    str = str.toString();

    // assume leading char padding if null
    if( bPadTrailing == null ) {
        bPadTrailing = false;
    }

    var padding = "";
    for( var i=0; i<(count - str.length); i++ ) {
        padding += padChar;
    }

    if( bPadTrailing ) {
        str = str + padding;
    } else {
        str = padding + str;
    }
    return str;
}

function padLeadingZeros( str, count ) {
    return padString( str, count, "0", false );
}

