//+ Jonas Raoni Soares Silva
//@ http://jsfromhell.com/forms/masked-input [v1.0]

//========================================================
// REQUIRES http://www.jsfromhell.com/geral/event-listener
//========================================================

/*

	MaskInput(field: HTMLInputElement, mask: String): void

		Adds the mask to a field.

			fieldfield that will receive the mask
			maskmask that will be applied




Default Rules

	a = A-Z and 0-9
	A = A-Z, accents and 0-9
	9 = 0-9
	C = A-Z and accents
	c = A-Z
	* = Any character


Special rules

	E = (Except) exception
	O = (Only) only


Mask creation

	Simple masks:
	In this kind of mask the user can't type more characters than the amount of
	characters in the mask.
	Example:
	telephone = (99)9999-9999
	date = 99/99/9999


	Special mask "rule^exceptions":
	This kind of mask is composed ty two parts, separated by "^",
	the left side specified the rule and the right one, the exceptions for the selected rule.
	Example:
	9^abc = The rule is to accept only numbers "9" and the exception are the characters a, b and c
	c^123 = Accepts only a-z characters and the exception are the numbers 1, 2 and 3


	Use of the special rules:
	it's similar to the special mask, but the left side has a different meaning,
	can be "E" (any character, except...) and "O" (only...)
	Example:
	E^abc: Accepts any character, except a, b and c
	O^123: Only allows the characters 1, 2 e 3

*/



MaskInput = function(f, m)
{
	function mask(e)
	{
		var patterns =
		{
		  "1": /[A-Z]/i,
		  "2": /[0-9]/,
		  "4": /[\xC0-\xFF]/i,
		  "8": /./
		};
		var rules =
		{
		  "a": 3,
		  "A": 7,
		  "9": 2,
		  "C": 5,
		  "c": 1,
		  "*": 8
		};

		function accept(c, rule)
		{
			for( var i = 1, r = rules[rule] || 0; i <= r; i<<=1 )
			{
				if(r & i && patterns[i].test(c))
					break;
      }
			return i <= r || c == rule;
		}


		var k, mC, r,
		c = String.fromCharCode( k = e.key ),
		l = f.value.length;

		(!k || k == 8 ? 1 : (r = /^(.)\^(.*)$/.exec(m)) && (r[0] = r[2].indexOf(c) + 1) + 1 ?
			r[1] == "O" ? r[0] : r[1] == "E" ? !r[0] : accept(c, r[1]) || r[0]
			: (l = (f.value += m.substr(l, (r = /[A|9|C|\*]/i.exec(m.substr(l))) ?
			r.index : l)).length) < m.length && accept(c, m.charAt(l))) || e.preventDefault();
	}


	for(var i in !/^(.)\^(.*)$/.test(m) && (f.maxLength = m.length), {keypress: 0, keyup: 1})
		addEvent(f, i, mask);
};




