Javascript掩码输入

  1 function _MaskAPI(){
  2     this.version = "0.4b";
  3     this.instances = 0;
  4     this.objects = {};
  5 }
  6 MaskAPI = new _MaskAPI();
  7 
  8 function Mask(m, t){
  9     this.mask = m;
 10     this.type = (typeof t == "string"? t : "string";
 11     this.error = [];
 12     this.errorCodes = [];
 13     this.value = "";
 14     this.strippedValue = "";
 15     this.allowPartial = false;
 16     this.id = MaskAPI.instances++;
 17     this.ref = "MaskAPI.objects['" + this.id + "']";
 18     MaskAPI.objects[this.id] = this;
 19 }
 20 
 21 // define the attach(oElement) function
 22 Mask.prototype.attach = function (o){
 23     $addEvent(o, "onkeydown""return " + this.ref + ".isAllowKeyPress(event, this);"true);
 24     $addEvent(o, "onkeyup""return " + this.ref + ".getKeyPress(event, this);"true);
 25     $addEvent(o, "onblur""this.value = " + this.ref + ".format(this.value);"true);
 26 }
 27 
 28 Mask.prototype.isAllowKeyPress = function (e, o){
 29     ifthis.type != "string" ) return true;
 30     var xe = new qEvent(e);
 31 
 32     if( ((xe.keyCode > 47&& (o.value.length >= this.mask.length)) && !xe.ctrlKey ) return false;
 33     return true;
 34 }
 35 
 36 Mask.prototype.getKeyPress = function (e, o, _u){
 37     this.allowPartial = true;
 38     var xe = new qEvent(e);
 39 
 40 //    var k = String.fromCharCode(xe.keyCode);
 41 
 42     if( (xe.keyCode > 47|| (_u == true|| (xe.keyCode == 8 || xe.keyCode == 46) ){
 43         var v = o.value, d;
 44         if( xe.keyCode == 8 || xe.keyCode == 46 ) d = true;
 45         else d = false
 46 
 47         ifthis.type == "number" ) this.value = this.setNumber(v, d);
 48         else ifthis.type == "date" ) this.value = this.setDateKeyPress(v, d);
 49         else this.value = this.setGeneric(v, d);
 50 
 51         o.value = this.value;
 52     }
 53     /* */
 54 
 55     this.allowPartial = false;
 56     return true;
 57 }
 58 
 59 Mask.prototype.format = function (s){
 60     ifthis.type == "number" ) this.value = this.setNumber(s);
 61     else ifthis.type == "date" ) this.value = this.setDate(s);
 62     else this.value = this.setGeneric(s);
 63     return this.value;
 64 }
 65 
 66 Mask.prototype.throwError = function (c, e, v){
 67     this.error[this.error.length] = e;
 68     this.errorCodes[this.errorCodes.length] = c;
 69     iftypeof v == "string" ) return v;
 70     return true;
 71 }
 72 
 73 Mask.prototype.setGeneric = function (_v, _d){
 74     var v = _v, m = this.mask;
 75     var r = "x#*", rt = [], nv = "", t, x, a = [], j=0, rx = {"x""A-Za-z""#""0-9""*""A-Za-z0-9" };
 76 
 77     // strip out invalid characters
 78     v = v.replace(new RegExp("[^" + rx["*"+ "]""gi"), "");
 79     if( (_d == true&& (v.length == this.strippedValue.length) ) v = v.substring(0, v.length-1);
 80     this.strippedValue = v;
 81     var b=[];
 82     forvar i=0; i < m.length; i++ ){
 83         // grab the current character
 84         x = m.charAt(i);
 85         // check to see if current character is a mask, escape commands are not a mask character
 86         t = (r.indexOf(x) > -1);
 87         // if the current character is an escape command, then grab the next character
 88         if( x == "!" ) x = m.charAt(i++);
 89         // build a regex to test against
 90         if( (t && !this.allowPartial) || (t && this.allowPartial && (rt.length < v.length)) ) rt[rt.length] = "[" + rx[x] + "]";
 91         // build mask definition table
 92         a[a.length] = { "chr": x, "mask": t };
 93     }
 94 
 95     var hasOneValidChar = false;
 96     // if the regex fails, return an error
 97     if!this.allowPartial && !(new RegExp(rt.join(""))).test(v) ) return this.throwError(1"The value \"" + _v + "\" must be in the format " + this.mask + ".", _v);
 98     // loop through the mask definition, and build the formatted string
 99     else if( (this.allowPartial && (v.length > 0)) || !this.allowPartial ){
100         for( i=0; i < a.length; i++ ){
101             if( a[i].mask ){
102                 while( v.length > 0 && !(new RegExp(rt[j])).test(v.charAt(j)) ) v = (v.length == 1? "" : v.substring(1);
103                 if( v.length > 0 ){
104                     nv += v.charAt(j);
105                     hasOneValidChar = true;
106                 }
107                 j++;
108             } else nv += a[i].chr;
109             ifthis.allowPartial && (j > v.length) ) break;
110         }
111     }
112     
113     ifthis.allowPartial && !hasOneValidChar ) nv = "";
114     ifthis.allowPartial ){
115         if( nv.length < a.length ) this.nextValidChar = rx[a[nv.length].chr];
116         else this.nextValidChar = null;
117     }
118 
119     return nv;
120 }
121 
122 Mask.prototype.setNumber = function(_v, _d){
123     var v = String(_v).replace(/[^\d.-]*/gi, ""), m = this.mask;
124     // make sure there's only one decimal point
125     v = v.replace(/\./"d").replace(/\./g, "").replace(/d/".");
126 
127     // check to see if an invalid mask operation has been entered
128     if!/^[\$]?((\$?[\+-]?([0#]{1,3},)?[0#]*(\.[0#]*)?)|([\+-]?\([\+-]?([0#]{1,3},)?[0#]*(\.[0#]*)?\)))$/.test(m) )
129         return this.throwError(1"An invalid mask was specified for the \nMask constructor.", _v);
130 
131     if( (_d == true&& (v.length == this.strippedValue.length) ) v = v.substring(0, v.length-1);
132 
133     ifthis.allowPartial && (v.replace(/[^0-9]/"").length == 0) ) return v;
134     this.strippedValue = v;
135 
136     if( v.length == 0 ) v = NaN;
137     var vn = Number(v);
138     if( isNaN(vn) ) return this.throwError(2"The value entered was not a number.", _v);
139 
140     // if no mask, stop processing
141     if( m.length == 0 ) return v;
142 
143     // get the value before the decimal point
144     var vi = String(Math.abs((v.indexOf("."> -1 ) ? v.split(".")[0] : v));
145     // get the value after the decimal point
146     var vd = (v.indexOf("."> -1? v.split(".")[1] : "";
147     var _vd = vd;
148 
149     var isNegative = (vn != 0 && Math.abs(vn)*-1 == vn);
150 
151     // check for masking operations
152     var show = {
153         "$" : /^[\$]/.test(m),
154         "(": (isNegative && (m.indexOf("("> -1)),
155         "+" : ( (m.indexOf("+"!= -1&& !isNegative )
156     }
157     show["-"= (isNegative && (!show["("|| (m.indexOf("-"!= -1)));
158 
159 
160     // replace all non-place holders from the mask
161     m = m.replace(/[^#0.,]*/gi, "");
162 
163     /*
164         make sure there are the correct number of decimal places
165     */
166     // get number of digits after decimal point in mask
167     var dm = (m.indexOf("."> -1 ) ? m.split(".")[1] : "";
168     if( dm.length == 0 ){
169         vi = String(Math.round(Number(vi)));
170         vd = "";
171     } else {
172         // find the last zero, which indicates the minimum number
173         // of decimal places to show
174         var md = dm.lastIndexOf("0")+1;
175         // if the number of decimal places is greater than the mask, then round off
176         if( vd.length > dm.length ) vd = String(Math.round(Number(vd.substring(0, dm.length + 1))/10));
177         // otherwise, pad the string w/the required zeros
178         else while( vd.length < md ) vd += "0";
179     }
180 
181     /*
182         pad the int with any necessary zeros
183     */
184     // get number of digits before decimal point in mask
185     var im = (m.indexOf("."> -1 ) ? m.split(".")[0] : m;
186     im = im.replace(/[^0#]+/gi, "");
187     // find the first zero, which indicates the minimum length
188     // that the value must be padded w/zeros
189     var mv = im.indexOf("0")+1;
190     // if there is a zero found, make sure it's padded
191     if( mv > 0 ){
192         mv = im.length - mv + 1;
193         while( vi.length < mv ) vi = "0" + vi;
194     }
195 
196 
197     /*
198         check to see if we need commas in the thousands place holder
199     */
200     if/[#0]+,[#0]{3}/.test(m) ){
201         // add the commas as the place holder
202         var x = [], i=0, n=Number(vi);
203         while( n > 999 ){
204             x[i] = "00" + String(n%1000);
205             x[i] = x[i].substring(x[i].length - 3);
206             n = Math.floor(n/1000);
207             i++;
208         }
209         x[i] = String(n%1000);
210         vi = x.reverse().join(",");
211     }
212 
213 
214     /*
215         combine the new value together
216     */
217     if( (vd.length > 0 && !this.allowPartial) || ((dm.length > 0&& this.allowPartial && (v.indexOf("."> -1&& (_vd.length >= vd.length)) ){
218         v = vi + "." + vd;
219     } else if( (dm.length > 0&& this.allowPartial && (v.indexOf("."> -1&& (_vd.length < vd.length) ){
220         v = vi + "." + _vd;
221     } else {
222         v = vi;
223     }
224 
225     if( show["$"] ) v = this.mask.replace(/(^[\$])(.+)/gi, "$"+ v;
226     if( show["+"] ) v = "+" + v;
227     if( show["-"] ) v = "-" + v;
228     if( show["("] ) v = "(" + v + ")";
229     return v;
230 }
231 
232 Mask.prototype.setDate = function (_v){
233     var v = _v, m = this.mask;
234     var a, e, mm, dd, yy, x, s;
235 
236     // split mask into array, to see position of each day, month & year
237     a = m.split(/[^mdy]+/);
238     // split mask into array, to get delimiters
239     s = m.split(/[mdy]+/);
240     // convert the string into an array in which digits are together
241     e = v.split(/[^0-9]/);
242     
243     if( s[0].length == 0 ) s.splice(01);
244 
245     forvar i=0; i < a.length; i++ ){
246         x = a[i].charAt(0).toLowerCase();
247         if( x == "m" ) mm = parseInt(e[i], 10)-1;
248         else if( x == "d" ) dd = parseInt(e[i], 10);
249         else if( x == "y" ) yy = parseInt(e[i], 10);
250     }
251 
252     // if year is abbreviated, guess at the year
253     if( String(yy).length < 3 ){
254         yy = 2000 + yy;
255         if( (new Date()).getFullYear()+5 < yy ) yy = yy - 100;
256     }
257 
258     // create date object
259     var d = new Date(yy, mm, dd);
260 
261     if( d.getDate() != dd ) return this.throwError(1"An invalid day was entered.", _v);
262     else if( d.getMonth() != mm ) return this.throwError(2"An invalid month was entered.", _v);
263 
264     var nv = "";
265 
266     for( i=0; i < a.length; i++ ){
267         x = a[i].charAt(0).toLowerCase();
268         if( x == "m" ){
269             mm++;
270             if( a[i].length == 2 ){
271                 mm = "0" + mm;
272                 mm = mm.substring(mm.length-2);
273             }
274             nv += mm;
275         } else if( x == "d" ){
276             if( a[i].length == 2 ){
277                 dd = "0" + dd;
278                 dd = dd.substring(dd.length-2);
279             }
280             nv += dd;
281         } else if( x == "y" ){
282             if( a[i].length == 2 ) nv += d.getYear();
283             else nv += d.getFullYear();
284         }
285 
286         if( i < a.length-1 ) nv += s[i];
287     }
288 
289     return nv;
290 }
291 
292 Mask.prototype.setDateKeyPress = function (_v, _d){
293     var v = _v, m = this.mask, k = v.charAt(v.length-1);
294     var a, e, c, ml, vl, mm = "", dd = "", yy = "", x, p, z;
295 
296     if( _d == true ){
297         while( (/[^0-9]/gi).test(v.charAt(v.length-1)) ) v = v.substring(0, v.length-1);
298         if( (/[^0-9]/gi).test(this.strippedValue.charAt(this.strippedValue.length-1)) ) v = v.substring(0, v.length-1);
299         if( v.length == 0 ) return "";
300     }
301 
302     // split mask into array, to see position of each day, month & year
303     a = m.split(/[^mdy]/);
304     // split mask into array, to get delimiters
305     s = m.split(/[mdy]+/);
306     // mozilla wants to add an empty array element which needs removed
307     if( s[0].length == 0 ) s.splice(0,1);
308     // convert the string into an array in which digits are together
309     e = v.split(/[^0-9]/);
310     // position in mask
311     p = (e.length > 0? e.length-1 : 0;
312     // determine what mask value the user is currently entering
313     c = a[p].charAt(0);
314     // determine the length of the current mask value
315     ml = a[p].length;
316 
317     forvar i=0; i < e.length; i++ ){
318         x = a[i].charAt(0).toLowerCase();
319         if( x == "m" ) mm = parseInt(e[i], 10)-1;
320         else if( x == "d" ) dd = parseInt(e[i], 10);
321         else if( x == "y" ) yy = parseInt(e[i], 10);
322     }
323     
324     
325     var nv = "";
326     var j=0;
327 
328     for( i=0; i < e.length; i++ ){
329         x = a[i].charAt(0).toLowerCase();
330     
331         if( x == "m" ){
332             z = ((/[^0-9]/).test(k) && c == "m");
333             mm++;
334             if( (e[i].length == 2 && mm < 10|| (a[i].length == 2 && c != "m"|| (mm > 1 && c == "m"|| (z && a[i].length == 2) ){
335                 mm = "0" + mm;
336                 mm = mm.substring(mm.length-2);
337             }
338             vl = String(mm).length;
339             ml = 2;
340             nv += mm;
341         } else if( x == "d" ){
342             z = ((/[^0-9]/).test(k) && c == "d");
343             if( (e[i].length == 2 && dd < 10|| (a[i].length == 2 && c != "d"|| (dd > 3 && c == "d"|| (z && a[i].length == 2) ){
344                 dd = "0" + dd;
345                 dd = dd.substring(dd.length-2);
346             }
347             vl = String(dd).length;
348             ml = 2;
349             nv += dd;
350         } else if( x == "y" ){
351             z = ((/[^0-9]/).test(k) && c == "y");
352             if( c == "y" ) yy = String(yy);
353             else {
354                 if( a[i].length == 2 ) yy = d.getYear();
355                 else yy = d.getFullYear();
356             }
357             if( (e[i].length == 2 && yy < 10|| (a[i].length == 2 && c != "y"|| (z && a[i].length == 2) ){
358                 yy = "0" + yy;
359                 yy = yy.substring(yy.length-2);
360             }
361             ml = a[i].length;
362             vl = String(yy).length;
363             nv += yy;
364         }
365 
366         if( ((ml == vl || z) && (x == c) && (i < s.length)) || (i < s.length && x != c ) ) nv += s[i];
367     }
368 
369     if( nv.length > m.length ) nv = nv.substring(0, m.length);
370 
371     this.strippedValue = (nv == "NaN"? "" : nv;
372 
373     return this.strippedValue;
374 }
375 
376 function qEvent(e){
377     // routine for NS, Opera, etc DOM browsers
378     if( window.Event ){
379         var isKeyPress = (e.type.substring(0,3== "key");
380 
381         this.keyCode = (isKeyPress) ? parseInt(e.which, 10) : 0;
382         this.button = (!isKeyPress) ? parseInt(e.which, 10) : 0;
383         this.srcElement = e.target;
384         this.type = e.type;
385         this.x = e.pageX;
386         this.y = e.pageY;
387         this.screenX = e.screenX;
388         this.screenY = e.screenY;
389         if( document.layers ){
390             this.altKey = ((e.modifiers & Event.ALT_MASK) > 0);
391             this.ctrlKey = ((e.modifiers & Event.CONTROL_MASK) > 0);
392             this.shiftKey = ((e.modifiers & Event.SHIFT_MASK) > 0);
393             this.keyCode = this.translateKeyCode(this.keyCode);
394         } else {
395             this.altKey = e.altKey;
396             this.ctrlKey = e.ctrlKey;
397             this.shiftKey = e.shiftKey;
398         }
399     // routine for Internet Explorer DOM browsers
400     } else {
401         e = window.event;
402         this.keyCode = parseInt(e.keyCode, 10);
403         this.button = e.button;
404         this.srcElement = e.srcElement;
405         this.type = e.type;
406         if( document.all ){
407             this.x = e.clientX + document.body.scrollLeft;
408             this.y = e.clientY + document.body.scrollTop;
409         } else {
410             this.x = e.clientX;
411             this.y = e.clientY;
412         }
413         this.screenX = e.screenX;
414         this.screenY = e.screenY;
415         this.altKey = e.altKey;
416         this.ctrlKey = e.ctrlKey;
417         this.shiftKey = e.shiftKey;
418     }
419     ifthis.button == 0 ){
420         this.setKeyPressed(this.keyCode);
421         this.keyChar = String.fromCharCode(this.keyCode);
422     }
423 }
424 
425 // this method will try to remap the keycodes so the keycode value
426 // returned will be consistent. this doesn't work for all cases,
427 // since some browsers don't always return a unique value for a
428 // key press.
429 qEvent.prototype.translateKeyCode = function (i){
430     var l = {};
431     // remap NS4 keycodes to IE/W3C keycodes
432     if!!document.layers ){
433         ifthis.keyCode > 96 && this.keyCode < 123 ) return this.keyCode - 32;
434         l = {
435             96:192,126:192,33:49,64:50,35:51,36:52,37:53,94:54,38:55,42:56,40:57,41:48,92:220,124:220,125:221,
436             93:221,91:219,123:219,39:222,34:222,47:191,63:191,46:190,62:190,44:188,60:188,45:189,95:189,43:187,
437             61:187,59:186,58:186,
438             "null"null
439         }
440     }
441     return (!!l[i]) ? l[i] : i;
442 }
443 
444 // try to determine the actual value of the key pressed
445 qEvent.prototype.setKP = function (i, s){
446     this.keyPressedCode = i;
447     this.keyNonChar = (typeof s == "string");
448     this.keyPressed = (this.keyNonChar) ? s : String.fromCharCode(i);
449     this.isNumeric = (parseInt(this.keyPressed, 10== this.keyPressed);
450     this.isAlpha = ((this.keyCode > 64 && this.keyCode < 91&& !this.altKey && !this.ctrlKey);
451     return true;
452 }
453 
454 // try to determine the actual value of the key pressed
455 qEvent.prototype.setKeyPressed = function (i){
456     var b = this.shiftKey;
457     if!&& (i > 64 && i < 91) ) return this.setKP(i + 32);
458     if( i > 95 && i < 106 ) return this.setKP(i - 48);
459     
460     switch( i ){
461         case 49case 51case 52case 53if( b ) i = i - 16break;
462         case 50if( b ) i = 64break;
463         case 54if( b ) i = 94break;
464         case 55if( b ) i = 38break;
465         case 56if( b ) i = 42break;
466         case 57if( b ) i = 40break;
467         case 48if( b ) i = 41break;
468         case 192if( b ) i = 126else i = 96break;
469         case 189if( b ) i = 95else i = 45break;
470         case 187if( b ) i = 43else i = 61break;
471         case 220if( b ) i = 124else i = 92break;
472         case 221if( b ) i = 125else i = 93break;
473         case 219if( b ) i = 123else i = 91break;
474         case 222if( b ) i = 34else i = 39break;
475         case 186if( b ) i = 58else i = 59break;
476         case 191if( b ) i = 63else i = 47break;
477         case 190if( b ) i = 62else i = 46break;
478         case 188if( b ) i = 60else i = 44break;
479 
480         case 106case 57379: i = 42break;
481         case 107case 57380: i = 43break;
482         case 109case 57381: i = 45break;
483         case 110: i = 46break;
484         case 111case 57378: i = 47break;
485 
486         case 8return this.setKP(i, "[backspace]");
487         case 9return this.setKP(i, "[tab]");
488         case 13return this.setKP(i, "[enter]");
489         case 16case 57389return this.setKP(i, "[shift]");
490         case 17case 57390return this.setKP(i, "[ctrl]");
491         case 18case 57388return this.setKP(i, "[alt]");
492         case 19case 57402return this.setKP(i, "[break]");
493         case 20return this.setKP(i, "[capslock]");
494         case 32return this.setKP(i, "[space]");
495         case 91return this.setKP(i, "[windows]");
496         case 93return this.setKP(i, "[properties]");
497 
498         case 33case 57371return this.setKP(i*-1"[pgup]");
499         case 34case 57372return this.setKP(i*-1"[pgdown]");
500         case 35case 57370return this.setKP(i*-1"[end]");
501         case 36case 57369return this.setKP(i*-1"[home]");
502         case 37case 57375return this.setKP(i*-1"[left]");
503         case 38case 57373return this.setKP(i*-1"[up]");
504         case 39case 57376return this.setKP(i*-1"[right]");
505         case 40case 57374return this.setKP(i*-1"[down]");
506         case 45case 57382return this.setKP(i*-1"[insert]");
507         case 46case 57383return this.setKP(i*-1"[delete]");
508         case 144case 57400return this.setKP(i*-1"[numlock]");
509     }
510     
511     if( i > 111 && i < 124 ) return this.setKP(i*-1"[f" + (i-111+ "]");
512 
513     return this.setKP(i);
514 }
515 
516 // define the addEvent(oElement, sEvent, sCmd, bAppend) function
517 function $addEvent(o, _e, c, _b){
518     var e = _e.toLowerCase(), b = (typeof _b == "boolean"? _b : true, x = (o[e]) ? o[e].toString() : "";
519     // strip out the body of the function
520     x = x.substring(x.indexOf("{")+1, x.lastIndexOf("}"));
521     x = ((b) ? (x + c) : (c + x)) + "\n";
522     return o[e] = (!!window.Event) ? new Function("event", x) : new Function(x);
523 }
posted @ 2008-01-25 19:30  蜡人张  阅读(1267)  评论(0编辑  收藏  举报