hjg
2024-07-09 30304784e82d4bba24121328da8eb8490aec4f4f
提交 | 用户 | 时间
58d006 1 /*
A 2  * Copyright (c) 2007 Josh Bush (digitalbush.com)
3  * 
4  * Permission is hereby granted, free of charge, to any person
5  * obtaining a copy of this software and associated documentation
6  * files (the "Software"), to deal in the Software without
7  * restriction, including without limitation the rights to use,
8  * copy, modify, merge, publish, distribute, sublicense, and/or sell
9  * copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following
11  * conditions:
12
13  * The above copyright notice and this permission notice shall be
14  * included in all copies or substantial portions of the Software.
15  * 
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23  * OTHER DEALINGS IN THE SOFTWARE. 
24  */
25  
26 /*
27  * Version: 1.0
28  * Release: 2007-07-25
29  */ 
30 (function($) {
31     //Helper Functions for Caret positioning
32     function getCaretPosition(ctl){
33         var res = {begin: 0, end: 0 };
34         if (ctl.setSelectionRange){
35             res.begin = ctl.selectionStart;
36             res.end = ctl.selectionEnd;
37         }else if (document.selection && document.selection.createRange){
38             var range = document.selection.createRange();            
39             res.begin = 0 - range.duplicate().moveStart('character', -100000);
40             res.end = res.begin + range.text.length;
41         }
42         return res;
43     };
44
45     function setCaretPosition(ctl, pos){
46         if(ctl.setSelectionRange){
47             ctl.focus();
48             ctl.setSelectionRange(pos,pos);
49         }else if (ctl.createTextRange){
50             var range = ctl.createTextRange();
51             range.collapse(true);
52             range.moveEnd('character', pos);
53             range.moveStart('character', pos);
54             range.select();
55         }
56     };
57     
58     //Predefined character definitions
59     var charMap={
60         '9':"[0-9]",
61         'a':"[A-Za-z]",
62         '*':"[A-Za-z0-9]"
63     };
64     
65     //Helper method to inject character definitions
66     $.mask={
67         addPlaceholder : function(c,r){
68             charMap[c]=r;
69         }
70     };
71     
72     //Main Method
73     $.fn.mask = function(mask,settings) {    
74         settings = $.extend({
75             placeholder: "_",
76             completed: null
77         }, settings);
78             
79         //Build Regex for format validation
80         var reString="^";    
81         for(var i=0;i<mask.length;i++)
82             reString+=(charMap[mask.charAt(i)] || ("\\"+mask.charAt(i)));                    
83         reString+="$";
84         var re = new RegExp(reString);
85
86         return this.each(function(){        
87             var input=$(this);
88             var buffer=new Array(mask.length);
89             var locked=new Array(mask.length);        
90
91             //Build buffer layout from mask
92             for(var i=0;i<mask.length;i++){
93                 locked[i]=charMap[mask.charAt(i)]==null;
94                 buffer[i]=locked[i]?mask.charAt(i):settings.placeholder;                    
95             }
96             
97             /*Event Bindings*/
98             input.focus(function(){                    
99                 checkVal();
100                 writeBuffer();
101                 setCaretPosition(this,0);        
102             });
103
104             input.blur(checkVal);
105             
106             //Paste events for IE and Mozilla thanks to Kristinn Sigmundsson
107             if ($.browser.msie) 
108                 this.onpaste= function(){setTimeout(checkVal,0);};                     
109             else if ($.browser.mozilla)
110                 this.addEventListener('input',checkVal,false);
111             
112             var ignore=false;  //Variable for ignoring control keys
113             
114             input.keydown(function(e){
115                 var pos=getCaretPosition(this);                                                    
116                 var k = e.keyCode;
117                 ignore=(k < 16 || (k > 16 && k < 32 ) || (k > 32 && k < 41));
118                 
119                 //delete selection before proceeding
120                 if((pos.begin-pos.end)!=0 && (!ignore || k==8 || k==46)){
121                     clearBuffer(pos.begin,pos.end);
122                 }    
123                 //backspace and delete get special treatment
124                 if(k==8){//backspace                    
125                     while(pos.begin-->=0){
126                         if(!locked[pos.begin]){                                
127                             buffer[pos.begin]=settings.placeholder;
128                             if($.browser.opera){
129                                 //Opera won't let you cancel the backspace, so we'll let it backspace over a dummy character.                                
130                                 writeBuffer(pos.begin);
131                                 setCaretPosition(this,pos.begin+1);
132                             }else{
133                                 writeBuffer();
134                                 setCaretPosition(this,pos.begin);
135                             }                                    
136                             return false;                                
137                         }
138                     }                        
139                 }else if(k==46){//delete
140                     clearBuffer(pos.begin,pos.begin+1);
141                     writeBuffer();
142                     setCaretPosition(this,pos.begin);
143                     return false;
144                 }else if (k==27){
145                     clearBuffer(0,mask.length);
146                     writeBuffer();
147                     setCaretPosition(this,0);
148                     return false;
149                 }
150                                     
151             });
152
153             input.keypress(function(e){                    
154                 if(ignore){
155                     ignore=false;
156                     return;
157                 }
158                 e=e||window.event;
159                 var k=e.charCode||e.keyCode||e.which;
160
161                 var pos=getCaretPosition(this);                    
162                 var caretPos=pos.begin;    
163                 
164                 if(e.ctrlKey || e.altKey){//Ignore
165                     return true;
166                 }else if ((k>=41 && k<=122) ||k==32 || k>186){//typeable characters
167                     while(pos.begin<mask.length){    
168                         var reString=charMap[mask.charAt(pos.begin)];
169                         var match;
170                         if(reString){
171                             var reChar=new RegExp(reString);
172                             match=String.fromCharCode(k).match(reChar);
173                         }else{//we're on a mask char, go forward and try again
174                             pos.begin+=1;
175                             pos.end=pos.begin;
176                             caretPos+=1;
177                             continue;
178                         }
179
180                         if(match)
181                             buffer[pos.begin]=String.fromCharCode(k);
182                         else
183                             return false;//reject char
184
185                         while(++caretPos<mask.length){//seek forward to next typable position
186                             if(!locked[caretPos])                            
187                                 break;                            
188                         }
189                         break;
190                     }
191                 }else
192                     return false;                                
193
194                 writeBuffer();
195                 if(settings.completed && caretPos>=buffer.length)
196                     settings.completed.call(input);
197                 else
198                     setCaretPosition(this,caretPos);
199                 
200                 return false;                
201             });
202
203             /*Helper Methods*/
204             function clearBuffer(start,end){
205                 for(var i=start;i<end;i++){
206                     if(!locked[i])
207                         buffer[i]=settings.placeholder;
208                 }                
209             };
210             
211             function writeBuffer(pos){
212                 var s="";
213                 for(var i=0;i<mask.length;i++){
214                     s+=buffer[i];
215                     if(i==pos)
216                         s+=settings.placeholder;
217                 }
218                 input.val(s);
219                 return s;
220             };
221             
222             function checkVal(){    
223                 //try to place charcters where they belong
224                 var test=input.val();
225                 var pos=0;
226                 for(var i=0;i<mask.length;i++){
227                     if(!locked[i]){
228                         while(pos++<test.length){
229                             //Regex Test each char here.
230                             var reChar=new RegExp(charMap[mask.charAt(i)]);
231                             if(test.charAt(pos-1).match(reChar)){
232                                 buffer[i]=test.charAt(pos-1);
233                                 break;
234                             }                                    
235                         }
236                     }
237                 }
238                 var s=writeBuffer();
239                 if(!s.match(re)){                            
240                     input.val("");    
241                     clearBuffer(0,mask.length);
242                 }                    
243             };                
244         });
245     };
246 })(jQuery);