I have always wanted a nice clean way to build form validators based on any kind of rule i would choose, however most of the times I stumbled upon a simple problem: How to get the cursor position inside a text-field? It’s easy in Mozilla, but what about IE?
The challenge was weird, but I finally got a way around, starting an idea here.
What I’ve done is I used Prototype to extend the Form Element Methods and simply add a version of selectionStart and selectionEnd for IE. After that, I just put them to work in a nice input wrapper class.

The idea behind is simple: Take a character sequence of your choice (I chose ~|~), being very careful not to pick something a user might actually write inside the input. Swap the current selection with the character sequence chosen above. Take the whole field value and get the starting point of the selection. Move the cursor back to the beginning of the selection. Make the selection blank.
Please wait until the end of the article to fully understand how this works (as you’ll see later on, i never lose the selection, if any has been made).
So, the code for the first part:

// @author Bogdan Nicolau (GPL)

// This is for IE
if (document.selection)
{
	Object.extend(Form.Element.Methods, {
 	 selectionStartF: function (element)
			{
				element = $(element);
				element.focus();
				var sel = document.selection.createRange();
				sel.text = "~|~";
				var start = element.value.indexOf("~|~");
				sel.moveStart("character", -3);
				sel.text = "";
				return start;
			},
			selectionEndF: function (element)
			{
				element = $(element);
				element.focus();
				var sel = document.selection.createRange();
				var len = sel.text.length;
				sel.text = "~|~";
				var start = element.value.indexOf("~|~");
				sel.moveStart("character", -3);
				sel.text = "";
				return start + len;
			}
	});
}
else if (window.addEventListener) // random Mozilla-only function
{
	Object.extend(Form.Element.Methods, {
 	 selectionStartF: function (element)
			{
				element = $(element);
				return element.selectionStart;
			},
			selectionEndF: function (element)
			{
				element = $(element);
				return element.selectionEnd;
			}
	});
}

Element.addMethods();
// @author Bogdan Nicolau (GPL)
// Extremely modified version of input wrapper by  Baron Schwartz  (GNU Lesser General Public License released)

 // Setup a wrapping object
 if ( typeof(WrapInput) === 'undefined' ) {
   WrapInput = new Object();
}

WrapInput.mask = {

   masks: {
      time: {
         rmask: new Array(/\d/, /\d/, /:/, /\d/, /\d/, /:/, /\d/, /\d/)
      }
   },

   /*
    * Finds all the elements with the class mask and masks them
    */
   searchAndApplyMask: function() {
      if ( document.getElementsByClassName ) { // Requires the Prototype library
         document.getElementsByClassName('mask').each(function(item) {
            Event.observe(item, 'keypress',
               WrapInput.mask.makeIt.bindAsEventListener(item), true);
         });
      }
   },

   /* Element bounded key trigger
    */
   makeIt: function(event) {
      var match = /mask_(\w+)/.exec(this.className);
      if ( match.length == 2 && WrapInput.mask.masks[match[1]] ) {
         var mask = WrapInput.mask.masks[match[1]];
         var key  = WrapInput.mask.getKey(event);

         if ( WrapInput.mask.isPrintable(key) ) {
            var ch      = String.fromCharCode(key);
            var begin = this.selectionStartF();
            var end = this.selectionEndF();
            var str = this.value.substr(0, begin) + ch + this.value.substr(end, this.value.length);
            if (!WrapInput.mask.check_input(mask.rmask, str, begin, end))
            {
            	Event.stop(event);
            }
         }
      }
   },

   /* Returns true if the key is a printable character.
    */
   isPrintable: function(key) {
      return ( key >= 32 && key < 127 );
   },

   /* Returns the key code
    */
   getKey: function(e) {
      return window.event ? window.event.keyCode
           : e            ? e.which
           :                0;
   },

   check_input: function(rmask, str, begin, end)
   {
     var correct = rmask;
     if (str.length > correct.length)
     {
     	return false;
     }

     for (var i= begin; i < end+1; i++)
     {
     	if (!str.charAt(i).match(correct[i]))
     	{
     		return false;
     	}
     }
     return true;
   }
};

// Init the input wrapper
WrapInput.mask.searchAndApplyMask();
Save and share: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • bodytext
  • Sphinn
  • del.icio.us
  • Mixx
  • Google
  • StumbleUpon
  • Technorati
  • YahooMyWeb

Comments

One Response to “Getting the cursor position inside a text-field and smart ways to build form validators”

  1. Hetal Prajapati on August 24th, 2009 1:04 pm

    Thanks,
    This is really very useful functions and it helped a lot….

Leave a Reply




Advertisements