﻿if(typeof ODAKeyCodeVersion != "function" || ODAKeyCodeVersion() != "1.0")
{
    alert('MaskTextbox requires ODAKeyCode.js v.1.0.');
}
if(typeof ODACommonLibrary != "function" || ODACommonLibrary() != "1.0")
{
    alert('MaskTextbox requires CommonLibrary.js v.1.0.');
}

var MaskTextboxes = new Array();

var MaskTextbox = new Class.create();
MaskTextbox.prototype = {

    // contructor for MaskTextbox takes 
    // 1.) control, or controlid
    // 2.) Mask
    // 3.) optional css class for blur state
    // 4.) optional css class for focus state
    // 5.) optional regex pattern (if null defaults to ".*" pattern
    // 6.) optional string to prompt user with when input is invalid
    // 7.) optional function to call if input is valid
    initialize: function(_textBox, _mask, _blurStyle, _focusStyle, _regExPattern, _invalidAlert, _onSuccess) 
    {
        MaskTextboxes[MaskTextboxes.length] = this;
        
        var tempRegExPattern = _regExPattern == null ? "^.*$" : _regExPattern;
        if(!startsWith(tempRegExPattern,"^"))
        { tempRegExPattern = "^" + tempRegExPattern; }
        if(!endsWith(tempRegExPattern,"$"))
        { tempRegExPattern = tempRegExPattern + "$"; }
        
        this.mask = _mask
        this.control = $(_textBox);
        this.blurStyle = _blurStyle == null ? "" : _blurStyle;
        this.focusStyle = _focusStyle == null ? "" : _focusStyle;
        this.regExPattern = tempRegExPattern;
        this.invalidAlert = _invalidAlert == null ? "The value entered does not match the exact pattern." : _invalidAlert;
        this.onSuccess = _onSuccess;
        
        this.showMask();
        
        // subscribe to the key-press event
        this.keyPressBoundListener = this.handleKeyPress.bindAsEventListener(this);
        Event.observe(this.control, "keypress", this.keyPressBoundListener);
        
        // subscribe to the key-down event
        this.keyDownBoundListener = this.handleKeyDown.bindAsEventListener(this);
        Event.observe(this.control, 'keydown', this.keyDownBoundListener);
        
        // subscribe to focus
        this.onFocusBoundListener = this.clearMask.bindAsEventListener(this);
        Event.observe(this.control, 'focus', this.onFocusBoundListener);
        
        // subscribe to blur
        this.onBlurBoundListener = this.validateField.bindAsEventListener(this);
        Event.observe(this.control, 'blur', this.onBlurBoundListener);
        
        // add a reference on the control back to this object
        //can't prototype a control
        //this.control.prototype.maskTextbox = this;
        //this.control.prototype.mask = this.mask;
    },
    
    validateField: function(){
        var value = $F(this.control);
        
        if(value.length > 0 && value.match(this.regExPattern) == null){
            alert(this.invalidAlert);
            moveCaretToEnd(this.control);     
            return;       
        }
        if(this.control.getValue().length > 0 && this.onSuccess != null)
        { this.onSuccess(); }
        this.showMask();
    },
    
    showMask: function(){
        if(this.blurStyle.length == 0 || this.focusStyle.length == 0){
            if(this.control.getValue().length == 0){
                this.control.value = this.mask;
                this.control.setStyle({color: "#999999"});
            }
        }
        else{
            if(this.control.hasClassName(this.focusStyle))
            {
                this.control.value = this.mask;
                this.control.removeClassName(this.focusStyle);
                this.control.addClassName(this.blurStyle);
            }
        }
    },
    
    clearMask: function(){
        if(this.blurStyle.length == 0 || this.focusStyle.length == 0){
            if(this.control.getValue() == this.mask){
                this.control.value = "";
                this.control.setStyle({color: "#000000"});
            }
        }
        else{
            if(this.control.hasClassName(this.blurStyle) && this.control.value == this.mask)
            {
                this.control.value = "";
                this.control.removeClassName(this.blurStyle);
                this.control.addClassName(this.focusStyle);
            }
        }
    },
    
    
    handleKeyDown: function(event){
        var odaKeyCode = new ODAKeyCode(event);
        
        // get the keyCode from the event
        var keyCode = odaKeyCode.keyCodeValue;
        
        // handle special keys
        if(odaKeyCode.IsSpecialKey)
        {
            return;
        }
        
        // get the current value of the control
        var curVal = this.control.getValue();
        
        // get the cursor position in the control (0-based position)
        var caret_position = getCaretPosition(this.control);
        
        // append the character
        if(caret_position == curVal.length)
        {
            curVal += keyCode;
        }
        else if(caret_position == 0)
        {
            curVal = keyCode + curVal;
        }
        else
        {
            var curValPieces = new Array();
            curValPieces[0] = curVal.substring(0,caret_position);
            curValPieces[1] = curVal.substring(caret_position, curVal.length);
            
            curVal = curValPieces[0] + keyCode + curValPieces[1];
        }
        
        
        // check to see if the pattern matches.  If so then add the character and continue.
        if(this.patternMatches(this.mask, curVal))
        {
            this.control.value = curVal;
        
            // increment the caret_position
            caret_position ++;
        
            // set the caret_position
            setCaretPosition(this.control, caret_position);
        
            // check to see if we need to append a hard-coded character from the mask
            if(parseInt(caret_position) < parseInt(this.mask.length)){
                var maskChar = this.mask.charAt(caret_position);
                while(maskChar != '#' &&
                    maskChar != 'A' &&
                    maskChar != '*' &&
                    maskChar != '?' &&
                    maskChar != '')
                {
                    this.control.value += maskChar;
                    caret_position++;
                    setCaretPosition(this.control, caret_position);
                    
                    if(parseInt(caret_position) < parseInt(this.mask.length)){
                        maskChar = this.mask.charAt(caret_position);
                    }
                    else
                    {
                        break;
                    }
                }
            }
        }
        
        // stop the normal event processing
        Event.stop(event);
        
    },
    
    patternMatches: function(mask, value){
        if(value.length > mask.length)
            {return true;}
        for(var j=0;j<mask.length; j++)
        {
            switch(mask.charAt(j))
            {
                case "#":
                    if(value.charAt(j) != "" && (value.charAt(j) < '0' || value.charAt(j) > '9'))
                        {return false;}
                    break;
                case "A":
                    if(value.charAt(j) == "" ||
                        (value.charAt(j) >= 'a' && value.charAt(j) <= 'z') ||
                        (value.charAt(j) >= 'A' && value.charAt(j) <= 'Z'))
                    {break;}
                    
                    return false;
                case "*":
                    if(value.charAt(j) == "" ||
                        (value.charAt(j) >= '0' && value.charAt(j) <= '9') ||
                        (value.charAt(j) >= 'a' && value.charAt(j) <= 'z') ||
                        (value.charAt(j) >= 'A' && value.charAt(j) <= 'Z'))
                    {break;}
                case "?":
                    break;
                default:
                    if(value.charAt(j) != "" && value.charAt(j) != mask.charAt(j))
                        {return false;}
                    break;
            }
        }
        return true;
    },
    
    handleKeyPress: function(e){
        var odaKey = new ODAKeyCode(e);
        if(odaKey.IsSpecialKey)
            return true;
            
        Event.stop(e);
        return false;
    },
  
    removeMask: function(){
        Event.stopObserving(this.control, 'keydown', this.keyDownBoundListener);
        Event.stopObserving(this.control, 'blur', this.onBlurBoundListener);
        Event.stopObserving(this.control, 'focus', this.onFocusBoundListener);
        Event.stopObserving(this.control, "keypress", this.keyPressBoundListener);
        
        var tempArr = new Array();
        for(var MaskTextboxIndex = 0; MaskTextboxIndex < MaskTextboxes.length; MaskTextboxIndex++)
        {
            var tempMaskTextbox = MaskTextboxes[index];
            if(tempMaskTextbox.control.id != this.control.id)
            {
                tempArr[tempArr.length] = tempMaskTextbox;
            }
        }
        MaskTextboxes = tempArr;
    }
  
};