/* DEPENDS ON YUI UTILITIES */

/********************************************************************
    IndexOf property for arrays... for more information follow link below
    http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:indexOf
*********************************************************************/

if (!Array.prototype.indexOf)
{
  Array.prototype.indexOf = function (elt /*, from*/)
  {
    var len = this.length;

    var from = Number(arguments[1]) || 0;
    from = (from < 0) ? Math.ceil(from) : Math.floor(from);
    if (from < 0)
      from += len;

    for (; from < len; from++)
    {
      if (from in this &&
          this[from] === elt)
        return from;
    }
    return -1;
  };
}

/********************************************************************
    Trim property for strings... for more information follow link below
    http://en.wikipedia.org/wiki/Trim_(programming)#JavaScript
*********************************************************************/
if (!String.prototype.trim) {
    String.prototype.trim = function () {
      return this.replace(/^\s+|\s+$/g, "");
    };
}

if (!String.prototype.toInt) {
    String.prototype.toInt = function () {
        var temp = this.replace(/[^\d-]/g, "");
        if (temp.length > 0) {
            return parseInt(temp, 10);
        } else {
            return 0;
        }
    };
}

/********************************************************************
    BASIC SETUP of namespaces, etc.
*********************************************************************/

var Dom = YAHOO.util.Dom;
var Event = YAHOO.util.Event;
var DDM = YAHOO.util.DragDropMgr;

if (!GLG) { 
    var GLG = {};
}

/********************************************************************
    MANIPULATION
*********************************************************************/

if (!GLG.Manipulation) {
    GLG.Manipulation = {};
}

// Gets the text content of an element
GLG.Manipulation.getTextContent = function (element) {
    if (!element) {
	    GLG.Debug.logJSError("No element passed in", "getInnerText");
	} else {
	    if (element.innerText) {
	        return element.innerText;
	    } else if (element.textContent) {
	        return element.textContent;
	    }
	} 
	return "";
};

// Returns the height of an element
GLG.Manipulation.getHeight = function (element) {
    if (!element) {
	    GLG.Debug.logJSError("No element passed in", "getHeight");
	} else {
	    var region = Dom.getRegion(element);
        var height = parseInt(region["bottom"], 10) - parseInt(region["top"], 10);
	    return height;	
	}
	return 0;
};

// Returns the width of an element
GLG.Manipulation.getWidth = function (element) {
    if (!element) {
	    GLG.Debug.logJSError("No element passed in", "getWidth");
	} else {
	    var region = Dom.getRegion(element);
        var width = parseInt(region["right"], 10) - parseInt(region["left"], 10);
	    return width;	
	}
	return 0;
};

// Scrolls the window to a location
GLG.Manipulation.scroll = function (x,y) {
	if (typeof(x) !== "number") {
	    GLG.Debug.logJSError("Invalid x passed in", "scroll");
	} else if (typeof(y) !== "number") {
	    GLG.Debug.logJSError("Invalid y passed in", "scroll");
	} else {
	    if (window.scroll) {
		    window.scroll(x,y);
	    } else if (window.scrollTo) {
		    window.scrollTo(x,y);
	    }
	}
};

// Scrolls the window to the Y coordinate of a specific element
GLG.Manipulation.scrollYToElement = function (element, offsetFromTop) {
	if (!element) {
	    GLG.Debug.logJSError("No element passed in", "scrollYToElement");
	} else if (typeof(offsetFromTop) !== "number") {
	    GLG.Debug.logJSError("offsetFromTop is invalid", "scrollYToElement");
	} else {
	    var elementRegion = Dom.getRegion(element);
	    var clientRegion = Dom.getClientRegion();
	    var clientHeight = clientRegion.bottom - clientRegion.top;
	    var documentHeight = Dom.getDocumentHeight();
	    var currentX = Dom.getDocumentScrollLeft();

	    var desiredY = elementRegion.top - offsetFromTop;
    	
	    // Make sure that we're not going past the beginning of the page or the end of the page
	    if (desiredY + clientHeight >= documentHeight) {
		    desiredY = documentHeight - clientHeight;
	    } else if (desiredY < 0) {
		    desiredY = 0; 
	    }
    	
        GLG.Manipulation.scroll(currentX, desiredY);
	}
};

// Toggles an element on the page from display block or none
GLG.Manipulation.Toggle = function (elToggle, elToggled, openCSS, closedCSS) {
    if (!elToggle) {
	    GLG.Debug.logJSError("Invalid elToggle", "Toggle");
	} else if (!elToggled) {
	    GLG.Debug.logJSError("Invalid elToggled", "Toggle");
	} else if (typeof(openCSS) !== "string") {
	    GLG.Debug.logJSError("Invalid openCSS", "Toggle");
	} else if (typeof(closedCSS) !== "string") {
	    GLG.Debug.logJSError("Invalid closedCSS", "Toggle");
	} else {
	         
        this.toggleClosed = function () {
            Dom.replaceClass(elToggle, openCSS, closedCSS);
            Dom.setStyle(elToggled, "display", "none");  
        };

        this.toggleOpen = function () {
            Dom.replaceClass(elToggle, closedCSS, openCSS);
            Dom.setStyle(elToggled, "display", "block");   
        };
         
        this.toggle = function(ev) {   
             if (Dom.hasClass(elToggle, closedCSS)){  
                this.toggleOpen();
             } else {  
                this.toggleClosed();
             }
             Event.stopEvent(ev);
        };
        
        Event.on(elToggle, "click", this.toggle, null, this);
     }  

    return this;
};

/********************************************************************
    FORMS
*********************************************************************/

if (!GLG.Forms) {
    GLG.Forms = {};
}

// Add behaviors to a text box to prevent users from entering characters besides numbers
GLG.Forms.addIntegerTextBehaviors = function (inputtext, allowNegative, minimum) {
	if (!inputtext) {
	    GLG.Debug.logJSError("inputtext is null", "addIntegerTextBehaviors");
	} else if (inputtext.tagName.toLowerCase() !== "input") {
	    GLG.Debug.logJSError("inputtext is not an input element", "addIntegerTextBehaviors");
	} else if (inputtext.type.toLowerCase() !== "text") {
	    GLG.Debug.logJSError("inputtext is not an text element", "addIntegerTextBehaviors");
	} else if (typeof(allowNegative) !== "boolean") {
	    GLG.Debug.logJSError("allowNegative is not valid", "addIntegerTextBehaviors");
	} else if (minimum && typeof(minimum) !== "number") {
	    GLG.Debug.logJSError("minimum is not valid", "addIntegerTextBehaviors");
	} else {
	
	    //Filter key presses
	    Event.on(inputtext, "keypress", function (ev) {
		
		    var keyCode = typeof(ev.charCode) === "undefined" ? ev.keyCode : ev.charCode;
		    var key = String.fromCharCode(keyCode);
		    var keyAsInt = parseInt(key, 10);
    	        	    
		    if (key === "v" && ev.ctrlKey === true) {
    			
			    // No cut and paste allowed
			    Event.stopEvent(ev);
                return false;
			    
		    } else if (key === "-" && allowNegative) {
    		
			    // Add/Remove the minus symbol
			    if (inputtext.value.substring(0,1) === "-") {
				    inputtext.value = inputtext.value.slice(1);
			    } else {
				    inputtext.value = "-" + inputtext.value;
			    }
			    Event.stopEvent(ev);
                return false;
    		
		    } else if (keyCode > 0 && keyAsInt.toString() === "NaN") {
    		
			    // No non-number characters allowed
			    Event.stopEvent(ev);
                return false;
    		
		    }
	    });
	    
	    // Clean up edge cases
	    Event.on(inputtext, "keyup", function (ev) {
    	    
    	    // The negative symbol is not in front
	        if (inputtext.value.indexOf("-") > 0) {
	            inputtext.value = "-" + inputtext.value.replace("-", "");
	        }
		    
	        // There is only a negative symbol
	        if (inputtext.value === "-") {
	            inputtext.value = "";
	        }
	        
        });
        
        // Revert to the minimum on blur if it exists
	    Event.on(inputtext, "blur", function (ev) {
	        if (minimum) {
	        
	            if (inputtext.value === "") {
	                inputtext.value = minimum.toString();
	            }

	            if (parseInt(inputtext.value, 10) < minimum) {
	                inputtext.value = minimum.toString();
	            }
	        }
	    });
	    
	}
};

// Combines a input filter with multiple regular expressions for validation
GLG.Forms.TextboxController = function (textbox, filterExp, validationExps, cssValid, cssInvalid) {
    
    if (!textbox || textbox.tagName.toLowerCase() !== "input" || textbox.type.toLowerCase() !== "text") {
	    GLG.Debug.logJSError("textbox is invalid", "TextboxController");
	} else if (filterExp && filterExp.constructor !== RegExp) {
	    GLG.Debug.logJSError("filterExp is invalid", "TextboxController");
	} else if (validationExps && typeof(validationExps) !== "object") {
	    GLG.Debug.logJSError("validationExps is invalid", "TextboxController");
	} else if (cssValid && typeof(cssValid) !== "string") {
	    GLG.Debug.logJSError("cssValid is not valid", "TextboxController");
	} else if (cssInvalid && typeof(cssInvalid) !== "string") {
	    GLG.Debug.logJSError("cssInvalid is not valid", "TextboxController");
	} else {
	
	    var pasted = false;
	    
	    // Catches cut and paste
	    function catchCutPaste(ev) {
	        if (ev.ctrlKey === true && ev.charCode === 118 ||ev.ctrlKey === true && ev.keyCode === 17) { 
		        pasted = true;
		        return true;
		    }
	    }
	    
	    // Pre-catch for IE and Safari
	    Event.on(textbox, "keydown", function (ev) {
	        if (catchCutPaste(ev)) {
	            return true;
	        }
	    }, null, this);
	    
	    //Filter key presses
	    Event.on(textbox, "keypress", function (ev) {
		    var keyCode = typeof(ev.charCode) === "undefined" ? ev.keyCode : ev.charCode;
    	    var key = String.fromCharCode(keyCode);
    	    
    	    if (catchCutPaste(ev)) {
	            return true;
	        }
    	    
		    if (keyCode > 0 && filterExp) {
		        var matches = key.match(filterExp);
		        if (matches) { 
		            
		            // Filtered in character
		            return true;
    		    
    		    } else { 
    		        
    		        // Filtered out character
		            Event.stopEvent(ev); 
                    return false;
                }
            }
	    }, null, this);
	
	    // Clean up
	    Event.on(textbox, "keyup", function (ev) {
    	    
    	    // Cut and Paste
    	    if (pasted) {
    	        if (filterExp) {
    	            var matches = textbox.value.match(filterExp);
    	            if (matches) {
    	                textbox.value =  matches.join("");   
    	            } else {
    	                textbox.value = "";
    	            }
    	        }
    	        pasted = false;
    	    }
    	    
    	    // Check validation
    	    var valid = false;
    	    if (validationExps && textbox.value.length > 0) {
    	        for (var i = 0; i < validationExps.length; i++) {
                    var validExp = validationExps[i];
                    if (this.isValid(validExp)){
                        valid = true;
                    }
                } 
    	    } else {
    	        valid = true;
    	    }
    	    
    	    //Update style
    	    if (cssValid && valid) {
    	        Dom.replaceClass(textbox, cssInvalid, cssValid);
    	    }
    	    if (cssInvalid && !valid) {
    	        Dom.replaceClass(textbox, cssValid, cssInvalid);
            }
        }, null, this);
        
        // Returns whether an expression is valid
        this.isValid = function (exp) {
            var validMatches = textbox.value.match(exp);
            if (validMatches && validMatches.length === 1 && validMatches[0] === textbox.value) {
               return true;
            }
            return false;
        };
        
        return this;
	}
	return null;
};

// Disables all form elements that are children of the element passed in
GLG.Forms.enableAllChildren = function(element, shouldEnable) {
    if (!element) {
	    GLG.Debug.logJSError("No element passed in", "enableAllChildren");
	} else if (typeof(shouldEnable) !== "boolean") {
	    GLG.Debug.logJSError("Invalid shouldEnable passed in", "enableAllChildren");
	} else {
	    
	    var inputs = element.getElementsByTagName("input");
	    for (var i = 0; i < inputs.length; i++) {
	        inputs[i].disabled = !shouldEnable;    
	    }
	    
	    var textareas = element.getElementsByTagName("textarea");
	    for (var j = 0; j < textareas.length; j++) {
	        textareas[j].disabled = !shouldEnable;    
	    }
	}
};

/********************************************************************
    REGULAR EXPRESSIONS
*********************************************************************/

if (!GLG.Regexp) {
    GLG.Regexp = {};
}

GLG.Regexp.intFilterPos = /[\d]+/g;

GLG.Regexp.intValidPos = /\d+/g;

GLG.Regexp.intFilter = /[\d-]+/g;

GLG.Regexp.intValid = /-?\d+/g;

/********************************************************************
    DEBUG
*********************************************************************/

if (!GLG.Debug) {
    GLG.Debug = {};
}

// Create log reader on DOM ready.
Event.onDOMReady(function() {
    if (/GLGUIDEBUG/.test(document.cookie)) {
        this.logReader = new YAHOO.widget.LogReader("LogReader");
    }
});
  
// Logs javascript error 			
GLG.Debug.logJSError = function (msg, fnName) {
	if (logReader) {
	    YAHOO.log(msg, "error", fnName);
	} else {
	    alert("Error:" + " " + fnName + "  - " + msg);
	}
};

// Logs javascript info
GLG.Debug.logInfo = function (msg, src) {
	YAHOO.log(msg, "info", src);
};

// Logs a web service info from ASP.NET AJAX 
GLG.Debug.logWSinfo = function () {
	YAHOO.log(arguments[0], "info", arguments[2]);
};

// Logs a web service error from ASP.NET AJAX 
GLG.Debug.logWSerror = function () {
	YAHOO.log(arguments[0], "error", arguments[2]);
};