// formatted-input.js [begin]

//////////////////////////////////////////////////////////////////////////
var FormattedInput = {
    LoggingUtils: {
        log: function(s) {
            if ( typeof console != 'undefined' && typeof console.log != 'undefined' ) console.log(s);
        },
        dir: function(e) {
            if ( typeof console != 'undefined' && typeof console.dir != 'undefined' ) console.dir(e);
        },
        dirxml: function(e) {
            if ( typeof console != 'undefined' && typeof console.dirxml != 'undefined' ) console.dirxml(e);
        }
    }, // Logging
    
    //////////////////////////////////////////////////////////////////////////
    KeyEventUtils: {
        GetKeyCode: function(eventObject) { // to be used by KeyPress event handlers
            var kc = eventObject.charCode || eventObject.keyCode || eventObject.which;
            FormattedInput.LoggingUtils.log('KeyEventUtils.GetKeyCode() kc='+kc);
            return kc;    
        },
        IgnoreKey: function(kc) {
            // note the issue with insert.  it is the same code as dash (45)
            // therefore we do not handle this here.
            // this allows tab, enter, page up/down, end, home, left arrow, right arrow, delete
            // tab = 9
            // enter = 13
            // esc = 27
            // page up = 33
            // page down = 34
            // end = 35
            // home = 36
            // left = 37
            // up = 38
            // right = 39
            // down = 40
            // ins = 45         -- also dash!!
            // del = 46
            
            //  0..15       17..31                  33..40                 46           112(F1)..123(F12)
            if (kc < 16 || (kc > 16 && kc < 32) || (kc > 32 && kc < 41) || kc == 46 || (kc >= 112 && kc<=123 ) ) {
                return true;
            }
            
            return false;
        },
        IsDigit: function(kc) { return ((kc>=48)&&(kc<=57)); },
        IsSlash: function(kc) { return kc==47; },
        IsColon: function(kc) { return kc==58; }
    }, // KeyEventUtils
    
    //////////////////////////////////////////////////////////////////////////
    // Handles elements with 'SearchPhoneTextbox' CSS class
    // Replaces behavior:url(/scripts/sphonetextbox.htc)
    SearchPhoneTextbox: {
        KeyPress: function(eventObject) {
            var kc = FormattedInput.KeyEventUtils.GetKeyCode(eventObject);
            if ( FormattedInput.KeyEventUtils.IgnoreKey(kc) )
                return;

	        var ctrl = this;
	        var txt = ctrl.value;
	        var words = txt.split("-");
    	    
	        FormattedInput.LoggingUtils.log("SearchPhoneTextbox.KeyPress() txt='"+txt+"' txt.length="+txt.length+" words.length="+words.length);
    	    
            //    48..57 (0-9)               ' '           '-'
	        if(!((kc > 47) && (kc < 58)) && (kc != 32) && (kc != 45)) { // not 0-9 and not space
		        alert('Suspect Phone should contain only numbers, dashes or spaces.');
		        return false;
	        }
    	
	        // digit or '-' or ' '
	        if(((kc > 47) && (kc < 58)) || (kc==45) || (kc==32)) {
		        if((kc == 45) && (words.length >= 3||txt.length == 0)) { // '-'
			        return false;
		        }
	        }
	        else {
		        return false;
	        }
        } // KeyPress()
    }, // SearchPhoneTextbox

    //////////////////////////////////////////////////////////////////////////
    // Handles elements with 'PhoneTextboxWExt' CSS class
    // Replaces behavior:url(/scripts/phonetextboxwext.htc)
    PhoneTextboxWExt: {
        KeyPress: function(eventObject) {
            var kc = FormattedInput.KeyEventUtils.GetKeyCode(eventObject);
            if ( FormattedInput.KeyEventUtils.IgnoreKey(kc) )
                return;

	        var ctrl = this;
	        var txt = ctrl.value;
	        var words = txt.split("-");
	        var len = txt.length;
	        var bNumberPressed = false;
	        var bEatKey = false;
    	    
	        FormattedInput.LoggingUtils.log("PhoneTextboxWExt.KeyPress() txt='"+txt+"' txt.length="+txt.length+" words.length="+words.length);
	        
	        if(txt == "")
	        {
		        if(!((kc > 47) && (kc < 58)))
		        {
			        alert('Phone number should be in the form of 555-555-5555 x-555');
			        return false;
		        }
	        }
	        
	        if(((kc > 47) && (kc < 58)) || (kc==45))  // && (kc != 48) && (kc != 8))
	        {
		        if((kc == 45) && (words.length >= 4))
		        {
			        bEatKey = true;
		        }
		        else
		        {
		            bNumberPressed = true;
		        }
	        }
	        else if ((words.length >= 3) && ((((kc > 47) && (kc < 58)) || (kc == 32) || (kc == 88) || (kc == 120)) || (kc == 45)))
	        {
	            bNumberPressed = true;
	        }
	        else if ((kc == 45) && (txt.length == 0))
	        {
	            bEatKey = true;
	        }
	        else
	        {
	            bEatKey = true;
	        }
	        
            ////
	        if((txt.charAt(len - 1) != '-') && (bNumberPressed) && (words.length < 3))
	        {
		        if(kc != 45)
		        {
			        if(len == 3)
			        {
			            FormattedInput.LoggingUtils.log('PhoneTextboxWExt.KeyPress() add dash to control value');
				        ctrl.value = txt + "-";
			        }
			        else if(words.length == 2)
			        {
				        if(words[1].length == 3)
				        {
				            FormattedInput.LoggingUtils.log('PhoneTextboxWExt.KeyPress() add dash to control value');
					        ctrl.value = txt + "-";
				        }	
			        }
		        }
	        }
	        else if(((txt == "-") || (txt == "--")) && (words.length < 3))
	        {
	            FormattedInput.LoggingUtils.log('PhoneTextboxWExt.KeyPress() clear the control value');
		        txt = "";
		        ctrl.value = txt;
	        }
	        else if((words.length == 3) && (txt.charAt(len - 1) == 'x' || txt.charAt(len - 1) == 'X'))
	        {
		        if(bNumberPressed && (kc != 45))
		        {
		            FormattedInput.LoggingUtils.log('PhoneTextboxWExt.KeyPress() add dash to control value');
			        ctrl.value = txt + "-";
		        }
	        }

            if ( bEatKey )
                return false;

        } // KeyPress()
    }, // SearchPhoneTextbox
    
    //////////////////////////////////////////////////////////////////////////
    // replaces behavior:url(/scripts/timetextbox.htc)
    TimeTextbox: {
        Initialize: function(i) {
            FormattedInput.LoggingUtils.log('TimeTextbox.Initialize() i='+i+' this.tagName'+this.tagName);
            var jq = jQuery(this);
            jq.keypress( FormattedInput.TimeTextbox.KeyPress ).blur( FormattedInput.TimeTextbox.HandleBlur )

//was
//             jq.filter(".TimeTextbox").mask('99:99',{placeholder:'_','completed':function(){FormattedInput.TimeTextbox.ValidateControl(this[0]);}})
//                     .change( FormattedInput.TimeTextbox.Change );

        },
        KeyPress: function(eventObject) {
            var kc = FormattedInput.KeyEventUtils.GetKeyCode(eventObject);
            if ( FormattedInput.KeyEventUtils.IgnoreKey(kc) )
                return;

            var bIsDigit = FormattedInput.KeyEventUtils.IsDigit(kc);
            var bIsColon = FormattedInput.KeyEventUtils.IsColon(kc);
            var bIsPrevCharColon = false;
            if ( bIsDigit == false && bIsColon == false )
                 return false;

	        var ctrl = this;
	        var txt = ctrl.value;
	        var len = txt.length;
	        var words = txt.split(":");
	        
	        if ( len >= 1 ) {
	            var prevChar = txt.charAt(len-1);
	            bIsPrevCharColon = prevChar == ':';
	        }
            
	        FormattedInput.LoggingUtils.log("TimeTextbox.KeyPress() txt='"+txt+"' len="+len+" words.length="+words.length+" bIsPrevCharColon="+bIsPrevCharColon);
	                        
            if ( bIsColon ) {
                if ( len == 0 )
                    return false; // cannot begin with :
            
                if ( bIsPrevCharColon )
                    return false; // no double :
                
                if ( words.length >= 2 )
                    return false; // no more than 1 :
            }
            else if ( bIsPrevCharColon == false ) {
                if ( len == 2 ) {
                    ctrl.value = txt + ":"; // 2 digits, add a :
                }
            }
        },        
        HandleBlur: function(eventObject) {
            FormattedInput.TimeTextbox.ValidateControl(this);
        },        
        ValidateControl: function(ctrl) {
            FormattedInput.LoggingUtils.log('TimeTextbox.ValidateControl() tagName='+ctrl.tagName+' value='+ctrl.value);
	        var txt = ctrl.value;
	        var len = txt.length;
	        var words = txt.split(":");    	
	        if(words.length == 2)
	        {
		        if(words[0].length == 1)
		        {
			        words[0] = "0" + words[0];
		        }
		        if(words[1].length == 1)
		        {
			        words[1] = "0" + words[1];
		        }
		        ctrl.value = words[0] + ":" + words[1];
    		    
		        jQuery(ctrl).trigger("change");
	        }    
        },    
        Change: function(eventObject) {
            FormattedInput.LoggingUtils.log('Change() fired!');
        }
    }, // TimeTextbox
    
    //////////////////////////////////////////////////////////////////////////
    // replaces behavior:url(/scripts/datetextbox.htc)
    DateTextbox: {
        Initialize: function(i) {
            var isCalendar = ( this.getAttribute("data-Control") == "Leadsonline.Web.Controls.Calendar" ? true : false );
            FormattedInput.LoggingUtils.log('DateTextbox.Initialize() i='+i+' this.tagName'+this.tagName+' isCalendar='+isCalendar);
            var jq = jQuery(this);

            if ( isCalendar ) {
                //@TODO: handle data-validate attribute (0/1)
                // data-validate == 1 means we need to validate (see testDate() in calendar.js)
                
                // @TODO: handle data-linkID and data-Begin (0/1) attributes
                // see checkDates() in calendar.js
                // see propChange() in calendar.js
                // data-linkID property gives a linked control's id attribute value
                // data-Begin == 1 means we're the LinkRange.start control

                jq.datepicker( {
                        dateFormat: 'm/d/yy',
                        changeFirstDay: false,
                        changeYear: false,
                        closeText: 'X',
                        constrainInput: true,
                        showOn: 'button',
                        showButtonPanel: false,
                        buttonImage: '/_media/calendar.gif',
                        buttonImageOnly: true,
                        duration: 0,
                        beforeShow: FormattedInput.DateTextbox.beforeShow,
                        onSelect: function(dateText) { FormattedInput.DateTextbox.ValidateValue(dateText,this); }
                        //onClose: function(dateOrArrayOfDates) { FormattedInput.DateTextbox.ValidateValue(dateOrArrayOfDates,this); }
                        } );
            }

            // want to be able to enter d/d/dd if possible
            jq.keypress( FormattedInput.DateTextbox.KeyPress ).blur( FormattedInput.DateTextbox.HandleBlur )
        },
        beforeShow: function(ctrl) {
            var startDate = new Date( parseInt(ctrl.getAttribute("data-StartDate.Year")),
                        parseInt(ctrl.getAttribute("data-StartDate.Month"))-1,
                        parseInt(ctrl.getAttribute("data-StartDate.Day")));
            var endDate = new Date( parseInt(ctrl.getAttribute("data-EndDate.Year")),
                        parseInt(ctrl.getAttribute("data-EndDate.Month"))-1,
                        parseInt(ctrl.getAttribute("data-EndDate.Day")));
            
            FormattedInput.LoggingUtils.log('Calendar.beforeShow() startDate='+startDate+' endDate='+endDate);
            return { minDate: startDate, maxDate: endDate, hideIfNoPrevNext: true };
        },
        KeyPress: function(eventObject) {
            var kc = FormattedInput.KeyEventUtils.GetKeyCode(eventObject);
            if ( FormattedInput.KeyEventUtils.IgnoreKey(kc) )
                return;
                
            var bIsDigit = FormattedInput.KeyEventUtils.IsDigit(kc);
            var bIsSlash = FormattedInput.KeyEventUtils.IsSlash(kc);
            var bIsPrevCharSlash = false;
            if ( bIsDigit == false && bIsSlash == false )
                 return false;

	        var ctrl = this;
	        var txt = ctrl.value;
	        var len = txt.length;
	        var words = txt.split("/");
	        
	        if ( len >= 1 ) {
	            var prevChar = txt.charAt(len-1);
	            bIsPrevCharSlash = prevChar == '/';
	        }

	        FormattedInput.LoggingUtils.log("DateTextbox.KeyPress() txt='"+txt+"' len="+len+" words.length="+words.length+" bIsPrevCharSlash="+bIsPrevCharSlash);
	                        
            if ( bIsSlash ) {
                if ( len == 0 )
                    return false; // cannot begin with /
            
                if ( bIsPrevCharSlash )
                    return false; // no double /
                
                if ( words.length >= 3 )
                    return false; // no more than 2 /
            }
            else if ( bIsPrevCharSlash == false ) {
                if ( len == 2 ) {
                    ctrl.value = txt + "/";
                }
                else if ( words.length == 2 && words[1].length == 2 ) {
                    ctrl.value = txt + "/";
                }
            }
        },
        HandleBlur: function(eventObject) {
            FormattedInput.DateTextbox.ValidateControl(this);
        },
        ValidateControl: function(ctrl) {
            FormattedInput.DateTextbox.ValidateValue(ctrl.value,ctrl);
        },
        ValidateValue: function(dateText,ctrl) {
            var txt = dateText;
	        var len = txt.length;
	        var words = txt.split("/");
	        
	        FormattedInput.LoggingUtils.log('DateTextbox.ValidateControl() txt='+txt+' len='+len+' words.length='+words.length);
	        
	        if(words.length == 3) {
	            // expected mm/dd/yyyy
	        
	            var reWrite = false;
// 	            if ( words[0].length == 1 ) {
// 	                words[0] = "0" + words[0];
// 	                reWrite = true;
// 	            }
	            
// 	            if ( words[1].length == 1 ) {
// 	                words[1] = "0" + words[1];
// 	                reWrite = true;
// 	            }
	        
	            if(words[2].length == 2) {
			        if(parseInt(words[2]) > 10)	{
				        words[2] = "19" + words[2];
			        }
			        else {
				        words[2] = "20" + words[2];
			        }
			        reWrite = true;
                }
                
                if ( reWrite ) {
			        ctrl.value = words[0] + "/" + words[1] + "/" + words[2];
		            jQuery(ctrl).trigger("change");
		            return;
                }                
	        }
	        
	        //jQuery(ctrl).css( 'background-color', 'yellow' );
        },    
        Change: function(eventObject) {
            FormattedInput.LoggingUtils.log('DateTextbox.Change() fired!');
        } 
    }, // DateTextbox

    //////////////////////////////////////////////////////////////////////////
    //
    EnhancedSelect: {
        Initialize: function(i) {
            FormattedInput.LoggingUtils.log('EnhancedSelect.Initialize() this='+this);
            if ( this.tagName != 'SELECT' ) return;

            $(this)
                .data( 'intervalID', 0 )
                .data( 'strSearch', "" )
                .data( 'flashCount', 0 )
                .data( 'flashIndex', 0 )
                .data( 'flashInterval', 0 )
                .data( 'inFlash', false )
                .data( 'bg', $(this).css("background-color") )
                .keypress( FormattedInput.EnhancedSelect.KeyPress );
        },
        KeyPress: function(eventObject) {
            var keyCode = FormattedInput.KeyEventUtils.GetKeyCode(eventObject);

		    window.clearInterval( $(this).data( 'intervalID') );

            if ( keyCode==13 /*enter*/ || 
                 keyCode==27 /*esc*/ || 
                 keyCode==9 /*tab*/ || 
                 keyCode==33 /*pageup*/ || 
                 keyCode==34 /*pagedown*/ ||
                 keyCode==35 /*end*/ ||
                 keyCode==36 /*home*/ ||
                 keyCode==38 /*up*/ ||
                 keyCode==40 /*down*/ )
            {
                // all the above keys are either able to leave the control or select something else in it
                return;
    		}

            var el = this;
		    $(this).data( 'intervalID', window.setInterval(function(){FormattedInput.EnhancedSelect.clearText(el);},1500) );
    		
		    var strSearch = $(this).data( 'strSearch' );
    		
		    // if this is the first letter, let the control handle the event
		    if ( strSearch == "" )
		    {
			    strSearch += String.fromCharCode(keyCode).toLowerCase();
			    $(this).data( 'strSearch', strSearch );
			    return;
		    }	
    			
		    // if this is a repeat (pump letter), then let the control handle the event
		    if (strSearch.length==1 && String.fromCharCode(keyCode)==strSearch)
		    {
			    return;
		    }
		    else
		    {
			    strSearch += String.fromCharCode(keyCode).toLowerCase();
			    $(this).data( 'strSearch', strSearch );
		    }								
    		
		    FormattedInput.EnhancedSelect.findText(this,strSearch);
    		
		    // we handled the event, so cancel it.
		    eventObject.preventDefault();
        },
        clearText: function(el) {
            FormattedInput.LoggingUtils.log('EnhancedSelect.clearText() el='+el);
            window.clearInterval( $(el).data( 'intervalID' ) );
            $(el).data( 'strSearch', "" );
        },
        findText: function(el,search) {
            var aOptions = el.options;
            FormattedInput.LoggingUtils.log('EnhancedSelect.findText() el='+el+' search='+search+' aOptions.length='+aOptions.length);
            for (i=0; i< aOptions.length; i++)
            {
	            if (aOptions[i].text.substr(0,search.length).toLowerCase()==search)
	            {
	                FormattedInput.LoggingUtils.log('EnhancedSelect.findText() found match at i='+i);
		            el.selectedIndex = i;	
		            return;		
	            }		
            }
            FormattedInput.EnhancedSelect.flashSelection(el);
        },
        flashSelection: function(el) {
            FormattedInput.LoggingUtils.log('EnhancedSelect.flashSelection() el='+el);
            if ( $(el).data( 'inFlash' ) == false ) {
                $(el).data( 'inFlash', true );
                $(el).data( 'flashIndex', el.selectedIndex );
                //$(el).css( 'background-color', 'yellow' );
                el.selectedIndex = -1;
                $(el).data( 'flashInterval', window.setInterval( function() { FormattedInput.EnhancedSelect.toggleFlash(el); }, 100 /*50*/ ) );
            }
        },
        toggleFlash: function(el) {
            FormattedInput.LoggingUtils.log('EnhancedSelect.toggleFlash() el='+el);
            var fc = $(el).data( 'flashCount' );
            var fi = $(el).data( 'flashIndex' );
            if ( fc <= 4 ) {
                if ( el.selectedIndex == fi ) {
                    el.selectedIndex = -1;
                    //$(el).css( 'background-color', 'yellow' );
                }
                else {
                    el.selectedIndex = fi;
                    //$(el).css( 'background-color', $(el).data( 'bg' ) );
                }
                FormattedInput.LoggingUtils.log('EnhancedSelect.toggleFlash() set selectedIndex='+el.selectedIndex);
                $(el).data( 'flashCount', fc+1 );
            }
            else {
                $(el).data( 'flashCount', 0 );
                window.clearInterval( $(el).data( 'flashInterval' ) );
                $(el).data( 'inFlash', false );
                //$(el).css( 'background-color', $(el).data( 'bg' ) );
                el.selectedIndex = fi;
                FormattedInput.LoggingUtils.log('EnhancedSelect.toggleFlash() set selectedIndex='+el.selectedIndex);
            }
        }
    } // EnhancedSelect
};

// standard jquery setup, "call me when the document is ready to work on"
jQuery(document).ready(function(){
    // moved all this code here so we will do a smart look over the DOM
    // we want to do as few traversals as possible, so lets create a selector that will match what we are interested in and then iterate the matches
    // performing a single selector that matches multiple items will mean single traversal and then matches over the result - much more optimal
    // in the below selector ".[text]" means class="[text]"
    // we iterate what the selector returns and then just run filter() function calls over each result.
    jQuery(".PhoneTextbox,.SearchPhoneTextbox,.PhoneTextboxWExt,.TimeTextbox,.DateTextbox,.DateTextBox,SELECT,.SSNTextbox,.SSNTextBox").each( 
        function(i) {
            var jq = jQuery(this);
            FormattedInput.LoggingUtils.log('[formatted-input.js] each() i='+i+' tagName='+this.tagName+' className='+this.className);
            
            // replaces behavior:url(/scripts/phonetextbox.htc)
            jq.filter(".PhoneTextbox").mask('999-999-9999',{placeholder:'_'});
            
            jq.filter(".SearchPhoneTextbox").keypress( FormattedInput.SearchPhoneTextbox.KeyPress );
            
            jq.filter(".PhoneTextboxWExt").keypress( FormattedInput.PhoneTextboxWExt.KeyPress );
            
            // replaces behavior:url(/scripts/timetextbox.htc)
            jq.filter(".TimeTextbox").each( FormattedInput.TimeTextbox.Initialize );
            
            // replaces behavior:url(/scripts/datetextbox.htc)
            jq.filter(".DateTextbox,.DateTextBox").each( FormattedInput.DateTextbox.Initialize );
            
            // replaces behavior:url(/scripts/ssntextbox.htc)
            jq.filter(".SSNTextbox,.SSNTextBox").mask('999-99-9999',{placeholder:'_'});
            
            jq.filter("SELECT").each( FormattedInput.EnhancedSelect.Initialize );

        });
});

// formatted-input.js [end]