1 /***********************************************************************
2 Masked Input version 1.1
3 ************************************************************************
5 Home page: http://www.angelwatt.com/coding/masked_input.php
9 License: This work is licensed under a Creative Commons Attribution-Share Alike
10 3.0 United States License http://creativecommons.org/licenses/by-sa/3.0/us/
13 - elm: [req] text input node to apply the mask on
14 - format: [req] string format for the mask
15 - allowed: [opt, '0123456789'] string with chars allowed to be typed
16 - sep: [opt, '\/:-'] string of char(s) used as separators in mask
17 - typeon: [opt, '_YMDhms'] string of chars in mask that can be typed on
18 - onbadkey: [opt, null] function to run when user types a unallowed key
19 - badkeywait: [opt, 0] used with onbadkey. Indicates how long (in ms) to lock
20 text input for onbadkey function to run
21 ***********************************************************************/
22 function MaskedInput(args)
24 if (args['elm'] === null || args['format'] === null) { return false; }
26 format = args['format'],
27 allowed = args['allowed'] || '0123456789',
28 sep = args['separator'] || '\/:-',
29 open = args['typeon'] || '_YMDhms',
30 onbadkey = args['onbadkey'] || function(){},
31 badwait = args['badkeywait'] || 0;
33 var locked = false, hold = 0;
36 el.onkeydown = KeyHandlerDown; //
37 el.onkeypress = KeyHandlerPress; // add event handlers to element
38 el.onkeyup = KeyHandlerUp; //
42 code = code || window.event, ch = '';
43 var keyCode = code.which, evt = code.type;
44 if (keyCode == null) { keyCode = code.keyCode; }
45 if (keyCode === null) { return ''; } // no key, no play
46 // deal with special keys
48 case 8: ch = 'bksp'; break;
49 case 46: // handle del and . both being 46
50 ch = (evt == 'keydown') ? 'del' : '.'; break;
51 case 16: ch = 'shift'; break;//shift
52 case 0:/*CRAP*/ case 9:/*TAB*/ case 13:/*ENTER*/
54 case 37: case 38: case 39: case 40: // arrow keys
55 ch = (!code.shiftKey &&
56 (code.charCode != 39 && code.charCode !== undefined)) ?
57 'etc' : String.fromCharCode(keyCode);
59 // default to thinking it's a character or digit
60 default: ch = String.fromCharCode(keyCode);
64 function KeyHandlerDown(e)
67 if (locked) { return false; }
69 if (el.value == '') { el.value = format; SetTextCursor(el,0); }
70 // Only do update for bksp del
71 if (key == 'bksp' || key == 'del') { Update(key); return false; }
72 else if (key == 'etc' || key == 'shift') { return true; }
75 function KeyHandlerPress(e)
78 if (locked) { return false; }
80 // Check if modifier key is being pressed; command
81 if (key=='etc' || e.metaKey || e.ctrlKey || e.altKey) { return true; }
82 if (key != 'bksp' && key != 'del' && key != 'etc' && key != 'shift') {
83 if (!GoodOnes(key)) { return false; }
86 else { return false; }
88 function KeyHandlerUp(e) { hold = 0; }
91 var p = GetTextCursor(el), c = el.value, val = '';
94 case (allowed.indexOf(key) != -1):
95 if (++p > format.length) { return false; } // if text csor at end
96 // Handle cases where user places csor before separator
97 while (sep.indexOf(c.charAt(p-1)) != -1 && p <= format.length) { p++; }
98 val = c.substr(0, p-1) + key + c.substr(p);
99 // Move csor up a spot if next char is a separator char
100 if (allowed.indexOf(c.charAt(p)) == -1
101 && open.indexOf(c.charAt(p)) == -1) { p++; }
103 case (key=='bksp'): // backspace
104 if (--p < 0) return false; // at start of field
105 // If previous char is a separator, move a little more
106 while (allowed.indexOf(c.charAt(p)) == -1
107 && open.indexOf(c.charAt(p)) == -1
109 val = c.substr(0, p) + format.substr(p,1) + c.substr(p+1);
111 case (key=='del'): // forward delete
112 if (p >= c.length) { return false; } // at end of field
113 // If next char is a separator and not the end of the text field
114 while (sep.indexOf(c.charAt(p)) != -1
115 && c.charAt(p) != '') { p++; }
116 val = c.substr(0, p) + format.substr(p,1) + c.substr(p+1);
117 p++; // Move position forward
119 case (key=='etc'): return true; // Catch other allowed chars
120 default: return false; // Ignore the rest
122 el.value = ''; // blank it first (Firefox issue)
123 el.value = val; // put updated value back in
124 SetTextCursor(el, p); // Set the text cursor
127 function GetTextCursor(node)
130 if (node.selectionStart >= 0) { return node.selectionStart; }
131 else if (document.selection) {// IE
132 var ntxt = node.value; // getting starting text
133 var rng = document.selection.createRange();
135 var start = node.value.indexOf('|%|');
136 rng.moveStart('character', -3);
138 // put starting text back in,
139 // fixes issue if all text was highlighted
143 } catch(e) { return false; }
145 function SetTextCursor(node, pos)
148 if (node.selectionStart) {
150 node.setSelectionRange(pos,pos);
152 else if (node.createTextRange) { // IE
153 var rng = node.createTextRange();
154 rng.move('character', pos);
157 } catch(e) { return false; }
161 if (allowed.indexOf(k) == -1 && k!='bksp' && k!='del' && k!='etc') {
162 var p = GetTextCursor(el); // Need to ensure cursor position not lost
163 locked = true; onbadkey();
164 // Hold lock long enough for onbadkey function to run
165 setTimeout(function(){locked=false; SetTextCursor(el,p);}, badwait);
169 function resetField() {
172 function setAllowed(a) {
176 function setFormat(f) {
180 function setSeparator(s) {
184 function setTypeon(t) {
189 resetField:resetField,
190 setAllowed:setAllowed,
192 setSeparator:setSeparator,