/**
 * Exemple d'utilisation: $(selector).constrain({datatype:'alpha', maxlength: 400})
 */

(function($) {
    $.fn.extend({
        //Helper Function for Caret positioning
		caretConstrain: function(begin, end) {
			if (this.length == 0) return;
			if (typeof begin == 'number') {
				end = (typeof end == 'number') ? end : begin;
				return this.each(function() {
					
					if (this.setSelectionRange) {
						this.focus();
						
						
						//e = jQuery.Event("keydown");
                        //e.which = 65;
                        //this.trigger(e);

						
						//this.setSelectionRange(begin, end + 1);
						
						//var evt = document.createEvent("KeyboardEvent");
						
                        /*if (this.val().length == end) {
                                evt.initKeyEvent("keypress", true, true, null, false, false, false, false, 0, 37);
                        } else {
                                evt.initKeyEvent("keypress", true, true, null, false, false, false, false, 0, this.val().charCodeAt(selEnd));
                        }*/
                        
                        /*evt.initKeyEvent("keypress", true, true, null, false, false, false, false, 0, 37);
                        this.dispatchEvent(evt);
                        
                        evt.initKeyEvent("keypress", true, true, null, false, false, false, false, 0, 39);
                        this.dispatchEvent(evt);*/

						
						
						// Workaround for FF overflow no scroll problem
                        // Trigger a "space" keypress.
                        /*var evt = document.createEvent("KeyboardEvent");
                        evt.initKeyEvent("keypress", true, true, null, false, false, false, false, 0,32);
                        this.dispatchEvent(evt);*/

                        // Trigger a "backspace" keypress.
                        /*evt = document.createEvent("KeyboardEvent");
                        evt.initKeyEvent("keypress", true, true, null, false, false, false, false, 8,0);
                        this.dispatchEvent(evt);*/
                        
                        
						this.setSelectionRange(begin, end);

					} else if (this.createTextRange) {
						var range = this.createTextRange();
						range.collapse(true);
						range.moveEnd('character', end);
						range.moveStart('character', begin);
						range.select();
					}
				});
			} else {
				if (this[0].setSelectionRange) {
					begin = this[0].selectionStart;
					end = this[0].selectionEnd;
				} else if (document.selection && document.selection.createRange) {
					/*
					var range = document.selection.createRange();
					begin = 0 - range.duplicate().moveStart('character', -100000);
					end = begin + range.text.length;
					*/
					
                    /*
					var txtarea = this[0];
					var txtlength = this.val().length;
                    var range = document.selection.createRange();
                    rangeCopy = range.duplicate();
                    rangeCopy.moveToElementText(txtarea);                    
                    
                    begin = rangeCopy.moveStart('character', -100000);
                    alert(begin);
                    
                    */
                    var field = this[0];
                    var range = document.selection.createRange();
                    
                    if (field.tagName == 'TEXTAREA') {
                        
                        rangeCopy = range.duplicate();
                        rangeCopy.moveToElementText(field);
                        rangeCopy.setEndPoint( 'EndToEnd', range );
                        
                        begin = rangeCopy.moveStart('character', -100000) - range.duplicate().moveStart('character', -100000);
                    } else {
                        begin = 0 - range.duplicate().moveStart('character', -100000);
                    }
                    
                    end = begin + range.text.length;
                    
					//alert(begin);
					
					/*
					var range = document.selection.createRange();
					
					var re = this[0].createTextRange();
					var rc = re.duplicate(); 
                    
                    re.moveToBookmark(range.getBookmark()); 
                    rc.setEndPoint('EndToStart', re); 

                    begin = rc.text.length;
                    end = range.text.length;
                    */
                    
                    /*
                    var textArea = this[0];
                    var range = document.selection.createRange();
                    rangeCopy = range.duplicate();
                    // Select all text
                    rangeCopy.moveToElementText(textArea);
                    // Now move 'dummy' end point to end point of original range
                    rangeCopy.setEndPoint( 'EndToEnd', range );
                    // Now we can calculate start and end points
                    begin = rangeCopy.text.length - range.text.length;
                    end = begin + range.text.length;
                    */

                    
 
					
					/*
					var val = this.val();
					var range = document.selection.createRange().duplicate();
					range.moveEnd("character", val.length)
					begin = (range.text == "" ? val.length : val.lastIndexOf(range.text));

					range = document.selection.createRange().duplicate();
					range.moveStart("character", -val.length);
					end = range.text.length;
					*/
					
					/*
					var r = document.selection.createRange();

					var re = this.createTextRange();
					var rc = re.duplicate();
					re.moveToBookmark(r.getBookmark());
					rc.setEndPoint('EndToStart', re);
					
					begin = rc.text.length;
					end = rc.text.length + r.text.length;
                    */

				}
				return { begin: begin, end: end };
			}
		}
	});
	
	$.fn.constrain = function(o){
	    var debug = '';
		var pasteEventName = ($.browser.msie ? 'paste' : 'input');
		var cContainers = this;
		var options = $.extend({},o);
		var exprreg = {
		    'alpha' : "[^a-zA-Z]",
		    'alphanumeric' : "[^a-zA-Z0-9]",
		    'alphanumericpoint' : "[^a-zA-Z0-9\.]",
		    'numeric' : "[^0-9]",
		    'float' : "[^0-9\.,]",
		    'city' : "[^a-zA-ZÀÁÂÃÄÅàáâãäåÒÓÔÕÖØòóôõöøÈÉÊËèéêëÇçÌÍÎÏìíîïÙÚÛÜùúûüÿÑñ' -]",
		    'name' : "[^a-zA-ZÀÁÂÃÄÅàáâãäåÒÓÔÕÖØòóôõöøÈÉÊËèéêëÇçÌÍÎÏìíîïÙÚÛÜùúûüÿÑñ' -]",
		    'namenumeric' : "[^a-zA-Z0-9ÀÁÂÃÄÅàáâãäåÒÓÔÕÖØòóôõöøÈÉÊËèéêëÇçÌÍÎÏìíîïÙÚÛÜùúûüÿÑñ'\. \f\n\r\t\v-]",
		    'namenumericponct' : "[^a-zA-Z0-9ÀÁÂÃÄÅàáâãäåÒÓÔÕÖØòóôõöøÈÉÊËèéêëÇçÌÍÎÏìíîïÙÚÛÜùúûüÿÑñ'\",\. \f\n\r\t\v-]",
		    'date' : "[^0-9\/]",
		    'phone' : "[^0-9+\. -]"
		};
		
		return cContainers.each(function(){
			var curElem = $(this);

			function getWhiteCharLess(texte)
			{
			    var regExp = new RegExp("\r\n|\r|\n","gi");
			    return texte.replace(regExp,"");
			};
			
			
			function insertText(texte, startPos, endPos) {
   		        var input = curElem;
    		    var buffer = input.val();
    		    endPos = (typeof endPos == 'number') ? endPos : startPos;
    		    //alert(buffer);
    		    if (options.maxlength) {
					var bufferWhiteCharLess = getWhiteCharLess(buffer);
					var texteWhiteCharLess = getWhiteCharLess(texte);
	
					StrLen = bufferWhiteCharLess.length + texteWhiteCharLess.length;
					if (StrLen >= options.maxlength && options.maxlength > 0){
					    var dispo = texteWhiteCharLess.length - (StrLen - options.maxlength);
					    var basedispo = texte.substr(0,dispo);
					    var baseWhiteCharLess = getWhiteCharLess(basedispo);

					    numberWhiteString =    basedispo.length - baseWhiteCharLess.length;
					    dispo += numberWhiteString;
					    texte = texte.substr(0,dispo);
						//$(curElem).val($(curElem).val().substr(0,options.maxlength + numberWhiteString));
				    }
    		    }
    		    
    		    
    		    buffer = buffer.substr(0,startPos) + texte + buffer.substr(endPos, buffer.length);
    		    input.val(buffer);
    		    //input.unbind('keypress');
    		    input.caretConstrain(startPos + texte.length);
    		    //input.bind('keypress',keyPressEvent);
    		    //caret(startPos + texte.length);
    		    //input.focus();
    		};
			
			function keyPressEvent(e)
			{
	            //if (e.which == 8 || e.which == 0 || e.which == 37 || e.which == 38 || e.which == 39 || e.which == 40 || e.ctrlKey || e.altKey || e.metaKey) {
	            if (e.which == 8 || e.which == 0 || (!$.browser.msie && (e.ctrlKey || e.altKey || e.metaKey))) {
	                return 1;
	            //} else if ((e.which >= 32 && e.which <= 125) || e.which > 186) {
	            } else {
	            
	                var buffer = '';
	      	        var pos = $(this).caretConstrain();
	      	        //alert(pos.begin);
	      	        if (pos.end > pos.begin) {
	      	            insertText(buffer, pos.begin, pos.end);
	      	        }
	      	        
	      	        //var pos = caret();
	      	        var c = String.fromCharCode(e.which);
	      	            
			        if (options.datatype) {
	      	            var datatype = options.datatype

	      	            if (exprreg[datatype]) {
	      	                var regtype = new RegExp(exprreg[datatype],"gi");
	      	                buffer = c.replace(regtype,"");
	      	            }
	                } else {
	                    buffer = c;
	                }
	                insertText(buffer,pos.begin);
	      	        return false;
	      	    }
	      	    
	      	    return false;
			};
			
			function pasteEvent()
			{
			    var pos = curElem.caretConstrain();
			    //var pos = caret();
			    var buffer = curElem.val();
			    
			    var prebuffer = buffer.substr(0,pos.begin)
			    var postbuffer = buffer.substr(pos.begin, buffer.length);
			    
			    if (options.datatype) {
	      	            var datatype = options.datatype

	      	            if (exprreg[datatype]) {
	      	                var regtype = new RegExp(exprreg[datatype],"gi");
	      	                
	      	                postbuffer = postbuffer.replace(regtype,"");
	      	                prebuffer = prebuffer.replace(regtype,"");
	      	                pos.begin -= buffer.substr(0,pos.begin) - prebuffer.length;
	      	            }
	                }
			   
			    curElem.val('');
			    insertText(postbuffer, 0);
			    insertText(prebuffer, 0);
			};
			
			$(curElem)
			    .bind('keypress', keyPressEvent)
			    .bind(pasteEventName, function(){
			        setTimeout(function() { pasteEvent(); }, 0);
			    });
		});
	}
	
})(jQuery);