/**
 * Copyright 2010 Allvesta, LLC
 *
 * This file and all of the source code contained within are the intellectual 
 * property of Allvesta, LLC. Any reproduction, description (either
 * written or verbal), or derivative of this code is strictly prohibited without
 * the written consent of Allvesta, LLC.
 *
 * -------------------------------------------------------------------------------
 *
 * Description: Common javascript functions.
 *      Author: Daniel Jennings (dsj@allvesta.com)
 *    Revision: A
 *  References: None
 *       Notes: None
 */


//add trim method to string class
String.prototype.trim = function() { 
	return this.replace(/^\s+|\s+$/g, ''); 
};

//string comparison
String.prototype.equalToIgnoreCase = function(str) {
	return this.toLowerCase() == str.toLowerCase();
};

//Array search
Array.prototype.exists = function(o) {
	for(var ii=0; ii<this.length; ii++) {
		if (this[ii] === o) {
			return true;
	    }
	}
	
	return false;
}


//Array search, get index
Array.prototype.indexOf = function(o) {
	for(var ii=0; ii<this.length; ii++) {
		if (this[ii] === o) {
			return ii;
	    }
	}
	
	return -1;
}


/**
 * Determine if this is part of a facebook application.
 * @return True is this is a facebook application, otherwise false.
 */
function isFacebook() {
	return document.URL.search('facebook') > 0;
}


/**
 * Generate a bot-safe email link.
 * @param email Email address
 * @param domain Email domain (assumed .com)
 * @param text Link text
 */
function generateEmailLink(email, domain, text) {
	document.write('<a href=mailto:' + email + '@' + domain + '.com>' + text + '</a>');
}


/**
 * Get an element.
 * @param element Element ID espected, but if DOM element is given will simply return.
 * @return DOM element.
 */
function getElement(element) {
    if (typeof element == 'string') { 
		element = document.getElementById(element); 
	}
	return element;
}


/**
 * Get an XML node's inner text value.
 * @param node XML node.
 * @return The given node's inner text value.
 */
function getInnerText(node) {
	 return (node.textContent || node.innerText || node.text);
}


/**
 * Get the value of a tag
 * @param xml XML object
 * @param tagName Name of tag.
 * @return Value of tag
 */
function getTagValue(xml, tagName) {
	return getInnerText(xml.getElementsByTagName(tagName).item(0));
}


/**
 * Get the value of a radio button.
 * @param name Name of the radio button.
 * @return Value of the radio button.
 */
function getRadioButtonValue(name) {
	var value = null;
	var radio = document.getElementsByName(name);
	for (var ii=0; ii<radio.length; ii++) {
		if (radio[ii].checked) {
			value = radio[ii].value;
			break;
		}
	}
	return value;
} //end method getRadioButtonValue


/**
 * Set the value of a radio button.
 * @param name Name of the radio button.
 * @param value Value to select
 */
function setRadioButtonValue(name, value) {
	var radio = document.getElementsByName(name);
	for (var ii=0; ii<radio.length; ii++) {
		if (value == radio[ii].value) {
			radio[ii].checked = true;
		}
		else {
			radio[ii].checked = false;
		}
	}
} //end method setRadioButtonValue


/**
 * Get the value of a select box.
 * @param element Select box DOM object.
 * @return Selected value.
 */
function getSelectBoxValue(element) {
	//get the element
	element = getElement(element);
    return element[element.selectedIndex].value;
} //end method getSelectBoxValue


/**
 * Get the value of a select box.
 * @param element Select box DOM object.
 * @return Selected inner HTML.
 */
function getSelectBoxSelection(element) {
	//get the element
	element = getElement(element);
    return element[element.selectedIndex].innerHTML;
} //end method getSelectBoxSelection


/**
 * Set the select box value.
 * @param element DOM Element object (or element ID).
 * @param selectedValue Value to select.
 */
function setSelectBoxValue(element, selectedValue) {
	//get the element
	element = getElement(element);
	
	//loop through all options, search for a match
	for(var ii=0; ii<element.length; ii++) {
		if (element.options[ii].value == selectedValue) {
			element.selectedIndex = ii;
			break;
		}
	}
} //end method setSelectBoxValue


/**
 * Determine if a select box has a given value.
 * @param element DOM element object (or element ID).
 * @param value Value to check
 * @return True if the value exists in the select box, otherwise false.
 */
function doesSelectBoxValueExist(element, value) {
	//initialize output
	var ret = false;
	
	//get the element
	element = getElement(element);
	
	//loop through all options, search for a match
	for(var ii=0; ii<element.length; ii++) {
		if (element.options[ii].value == value) {
			ret = true;
			break;
		}
	}
	
	return ret;
} //end method doesSelectBoxValueExist


/**
 * Set a cookie.
 * @param name Name of the cookie.
 * @param value Value of the cookie.
 * @param expireNumDays (Optional) Number of days until expiration.
 * NOTE: modified from: http://www.w3schools.com/JS/js_cookies.asp
 */
function setCookie(name, value, expireNumDays) {
	var exdate = new Date();
	exdate.setDate(exdate.getDate() + expireNumDays);
	document.cookie = name + "=" + escape(value) + ((expireNumDays == null) ? "" : ";expires=" + exdate.toGMTString());
} //end method setCookie


/**
 * Get a cookie.
 * @param name Name of the cookie.
 * @return Value of the cookie.
 * NOTE: modified from: http://www.w3schools.com/JS/js_cookies.asp
 */
function getCookie(name) {
	//initialize output
	var value = "";

	if (document.cookie.length > 0) {
		var start_index = document.cookie.indexOf(name + "=");

		if (start_index != -1) { 
			start_index = start_index + name.length + 1; 
			var end_index = document.cookie.indexOf(";", start_index);
			
			if (end_index == -1) {
				end_index = document.cookie.length;
			}

			value = unescape(document.cookie.substring(start_index, end_index));
		} //end if
	} //end if

	return value;
} //end method getCookie
 


/**
 * Create an XML HTTP request object.
 * @return An XML HTTP request object.
 */
function createXMLHTTPRequestObject(){
	//create variable to hold request object
	var request_obj;

	//get the browser name
	var browser = navigator.appName;

	//depending on the browser name create the object
	if (browser == "Microsoft Internet Explorer") {
		request_obj = new ActiveXObject("Microsoft.XMLHTTP");
	}
	else {
		request_obj = new XMLHttpRequest();
	}

	return request_obj;
} //end method createXMLHTTPRequestObject


/**
 * Trim a text field.
 * @param subject Original text.
 * @param maxNumCharacters Maximum number of characters to allow.
 * @param appendedText Text to append of text is trimmed. Defaults to "...".
 * @return Trimmed text.
 */
function trimText(text, maxNumCharacters, appendedText) {
    //only trim if number of number of characters is greater than max
    if (text.length > maxNumCharacters) {
		if (appendedText == null) {
			appendedText = '...';
		}

        text = text.substring(0, maxNumCharacters).trim() + appendedText;
    }

    return text;
} //end method trimText


/**
 * Mimics the PHP wordwrap function.
 * @param str String to wrap.
 * @param width The width to wrap.
 * @param breakStr The break string.
 * @param cut Flag indicating whether to cut words.
 * @return The wrapped string.
 *
 * NOTE: modified from http://kevin.vanzonneveld.net/techblog/article/javascript_equivalent_for_phps_wordwrap/
 */
function wordwrap(str, width, breakStr, cut) {
    //use PHP Defaults
    var m = ((arguments.length >= 2) ? arguments[1] : 75   );
    var b = ((arguments.length >= 3) ? arguments[2] : "\n" );
    var c = ((arguments.length >= 4) ? arguments[3] : false);
 
    var i, j, l, s, r;
 
    str += '';
 
    if (m < 1) {
        return str;
    }
 
    for (i = -1, l = (r = str.split("\n")).length; ++i < l; r[i] += s) {
        for(s = r[i], r[i] = ""; s.length > m; r[i] += s.slice(0, j) + ((s = s.slice(j)).length ? b : "")){
            j = c == 2 || (j = s.slice(0, m + 1).match(/\S*(\s)?$/))[1] ? m : j.input.length - j[0].length || c == 1 && m || j.input.length + (j = s.slice(m).match(/^\S*/)).input.length;
        }
    }
 
    return r.join("\n");
} //end method wordwrap


/**
 * Get the key that was pressed.
 * @param event Key press event.
 * @return The keycode for the key that was pressed.
 */
function getKeyPress(event) {
	if (window.event) {
		return window.event.keyCode; //IE
	}
	else if (event.which) {
		return event.which; //Netscape/Firefox/Opera
	}
	else {
		return null;
	}
} //end method getKeyPress


/**
 * Determine if a keypress was enter.
 * @param event The keypress event
 * @return True if this was enter, otherwise false
 */
function isEnter(event) {
	return getKeyPress(event) == 13;
}


/**
 * Hide an element.
 * @param element DOM Element object (or element ID) to hide.
 */
function hideElement(element) {
	//get the element
	element = getElement(element);
	
	//change style
	if (element != null) {
		if ((element.style.visibility == '') || (element.style.visibility == 'visible')) {
			element.style.visibility = 'hidden';
			element.style.display = 'none';
		}
	}
} //end method hideElement


/**
 * Show an element.
 * @param element DOM Element object (or element ID) to show.
 */
function showElement(element, displayType) {
	//see if display type was given
	if (displayType == null){
		displayType = 'block';
	}

	//get the element
	element = getElement(element);
	
	//change style
	if (element != null) {
		if ((element.style.visibility == '') || (element.style.visibility == 'hidden')) {
			element.style.visibility = 'visible';
			element.style.display = displayType;
		}
	}
} //end method showElement


/**
 * Show/Hide an element.
 * @param element DOM Element object (or element ID) to show/hide.
 */
function showHideElement(element) {
	//get the element
	element = getElement(element);
	
	//change style
	if (element.style.visibility == 'hidden') {
		element.style.visibility = 'visible';
		element.style.display = 'block';
	}
	else {
		element.style.visibility = 'hidden';
		element.style.display = 'none';
	}
} //end method showHideElement



/*************************************************************************************
 *									Style Sheet Methods
 *************************************************************************************/

 /**
 * Checks a given class attribute for the presence of a given class.
 * @param element DOM Element object (or element ID) to add the class to
 * @param className Name of the class.
 * @param True if the exists, otherwise false.
 *
 * @reference http://fluidmind.org/software/javascript/css-class-functions.php
 */
function checkForClass(element, className) {
	//get the element
	element = getElement(element);

    if (element.className == '') {
        return false;
    } 
	else {
        return new RegExp('\\b' + className + '\\b').test(element.className);
    }
} //end method checkForClass


/**
 * Adds a class to an element's class attribute.
 * @param element DOM Element object (or element ID) to add the class to
 * @param className Name of the class to add.
 *
 * @reference http://fluidmind.org/software/javascript/css-class-functions.php
 */
function addClass(element, className) {
	//get the element
	element = getElement(element);
	
	//check if class already exists
    if (!checkForClass(element, className)) {
        element.className += (element.className ? ' ' : '') + className;
    }
} //end method addClass


/**
 * Removes a class from an element's class attribute
 * @param element DOM Element object (or element ID) to add the class to
 * @param className Name of the class to remove.
 *
 * @reference http://fluidmind.org/software/javascript/css-class-functions.php
 */
function removeClass(element, className) {
    //get the element
	element = getElement(element);

	//make sure class exists
    if (checkForClass(element, className)) {
        element.className = element.className.replace((element.className.indexOf(' ' + className) >= 0 ? ' ' + className : className), '');
    }
} //end method removeClass


/**
 * Set the class of an element.
 * @param element DOM Element object (or element ID) to add the class to
 * @param className Class to use
 */
function setClass(element, className) {
	//get the element
	element = getElement(element);
	
	//change the class
	element.className = className;
} //end method setClass


/**
 * Determing if a given symbol is valid
 */
//TODO: move to stock functions class
function isSymbolValid(symbol) {
    //initialize output
    var ret = false;

    if (symbol.length > 0) {
        //create http request object
        var http = createXMLHTTPRequestObject();

        //open URL for php data provider
        var url = COMMON_FILE_URL + "services/stock/is_symbol_valid.php?symbol=" + symbol + "&rnd=" + Math.random();
        http.open("GET", url, false);
        http.send(null);

        //make sure that the transaction has finished
        if (http.readyState == 4) {
            //make sure valid response is received from the server
            if(http.status == 200) {
                var is_valid = getTagValue(http.responseXML, 'is_valid');
                
                if (is_valid == '1') {
                    ret = true;
                }
            } //end if
        } //end if
    } //end if
    
    return ret;
} //end method isSymbolValid


/**
 * Get the current price for a stock
 * @param symbol Stock symbol
 */
//TODO: move to stock functions class
function getCurrentPrice(symbol) {
	//init output
	var price = null;
	
	try {
		//create http request object
		var http = createXMLHTTPRequestObject();
	
		//open URL for php data provider
		var url = COMMON_FILE_URL + "services/stock/current_stock_data.php?symbol=" + symbol;
		http.open("GET", url, false);
		http.send(null);
		
		//make sure valid response is received from the server
		if (http.readyState == 4) {
			if (http.status == 200) {
		     	var response = http.responseXML;
		     	price = getTagValue(response, 'current_price');
			}
		}
	}
	catch (exception) {
		//do nothing
	}
        
	return price;
} //end method getCurrentPrice




/*
 * Suggestion Functions
 */

/**
 * Clear and hide the suggestion box.
 */
function clearSuggestion() {
	hideElement('suggestion_div');
	document.getElementById('suggestion_form').reset();
}

/**
 * Show the suggestion box.
 */
function showSuggestion() {
	showElement('suggestion_div');
	document.getElementById('suggestion').focus();
}


/**
 * Enable/Disable the suggestion button
 */
function enableDisableSuggestionSubmit() {
	var suggestion = document.getElementById('suggestion').value.trim();
	if (suggestion.length > 0) {
		document.getElementById('suggestion_submit_btn').disabled = false;
	}
	else {
		document.getElementById('suggestion_submit_btn').disabled = true;
	}
}


/**
 * Reset a date
 * @param date Date to reset
 * @return Reset date
 */
function resetTime (date) {
	date.setHours(0);
	date.setMinutes(0);
	date.setSeconds(0);
	date.setMilliseconds(0);
	return date;
}


/**
 * Submit a suggestion
 */
function submitSuggestion() {
	//get the suggestion text
	var suggestion = document.getElementById('suggestion').value.trim();
	
	//validate inputs
	if (suggestion.length == 0) {
		alert('You must provide a suggestion.');
	}
	else {
		//create http request object
	    var http = createXMLHTTPRequestObject();
	
	    //open URL for php data provider
	    var url = COMMON_FILE_URL + "services/submit_suggestion.php";
	    http.open("POST", url, false);
	    http.setRequestHeader("Content-type", "application/x-www-form-urlencoded;charset=UTF-8;");
	
	    //send the data
	    var payload = "suggestion=" + suggestion + "&rnd=" + Math.random();
	    http.send(payload);
	
	    //make sure valid response is received from the server
	    if(http.status == 200) {
	        try {
	            //retreive success flag
	            var response = http.responseXML;
	            var success = getTagValue(response, 'success');
	
	            if (success == '1') {
	            	alert('Thank you for the suggestion!');
	            }
	            else {
	                alert('There was a problem submitting the suggestion. Please contact customer service.');
	            }
	        }
	        catch (exception) {
	        	alert('There was a problem submitting the suggestion. Please contact customer service.');
	        }
	    } //end if
	    
	    //clear the suggestion
		clearSuggestion();
	} //end else
} //end method submitSuggestion


/**
 * Get the version of Internet Explorer (IE) being used
 * @return The version of IE, -1 if no version detected
 */
function getInternetExplorerVersion()
{
  var ret = -1;
  
  if (isInternetExplorer())
  {
    var reg_exp  = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
    if (reg_exp.exec(navigator.userAgent) != null)
    {
    	ret = parseFloat(RegExp.$1);
    }
  }
  
  return ret;
}


/**
 * Determine if this is Internet Explorer (IE)
 * @return True if this is IE, otherwise false
 */
function isInternetExplorer()
{
	return navigator.appName == 'Microsoft Internet Explorer';
}


/**
 * Determine if the browser supports canvas
 * @return True if the browser supports canvas
 */
function supportsCanvas() 
{
	  return !!document.createElement('canvas').getContext;
}
