1+ /**
2+ * Form Field Masking
3+ * Provides dynamic input masking for form fields with various formats
4+ */
5+
6+ function onLoad ( ) {
7+ var masker = new FormFieldMasker ( ) ;
8+ masker . initializeMasks ( ) ;
9+ }
10+
11+ function onChange ( control , oldValue , newValue , isLoading ) {
12+ if ( isLoading ) return ;
13+
14+ var masker = new FormFieldMasker ( ) ;
15+ masker . applyMask ( control , newValue ) ;
16+ }
17+
18+ var FormFieldMasker = Class . create ( ) ;
19+ FormFieldMasker . prototype = {
20+ initialize : function ( ) {
21+ // Predefined mask patterns
22+ this . masks = {
23+ phone : {
24+ pattern : '(###) ###-####' ,
25+ placeholder : '_' ,
26+ allowedChars : / [ 0 - 9 ] /
27+ } ,
28+ ssn : {
29+ pattern : '###-##-####' ,
30+ placeholder : 'X' ,
31+ allowedChars : / [ 0 - 9 ] / ,
32+ sensitive : true
33+ } ,
34+ creditCard : {
35+ pattern : '#### #### #### ####' ,
36+ placeholder : '_' ,
37+ allowedChars : / [ 0 - 9 ] / ,
38+ sensitive : true
39+ } ,
40+ date : {
41+ pattern : '##/##/####' ,
42+ placeholder : '_' ,
43+ allowedChars : / [ 0 - 9 ] /
44+ } ,
45+ currency : {
46+ pattern : '$ ###,###.##' ,
47+ placeholder : '0' ,
48+ allowedChars : / [ 0 - 9 . ] /
49+ } ,
50+ ipAddress : {
51+ pattern : '###.###.###.###' ,
52+ placeholder : '_' ,
53+ allowedChars : / [ 0 - 9 ] /
54+ }
55+ } ;
56+
57+ // Field to mask mapping
58+ this . fieldMasks = { } ;
59+ } ,
60+
61+ initializeMasks : function ( ) {
62+ var fields = g_form . getFields ( ) ;
63+ fields . forEach ( function ( field ) {
64+ var maskType = this . _getMaskType ( field . getName ( ) ) ;
65+ if ( maskType ) {
66+ this . fieldMasks [ field . getName ( ) ] = maskType ;
67+ this . _setupField ( field . getName ( ) , maskType ) ;
68+ }
69+ } , this ) ;
70+ } ,
71+
72+ applyMask : function ( fieldName , value ) {
73+ var maskType = this . fieldMasks [ fieldName ] || this . _getMaskType ( fieldName ) ;
74+ if ( ! maskType || ! value ) return ;
75+
76+ var mask = this . masks [ maskType ] ;
77+ if ( ! mask ) return ;
78+
79+ // Clean the input value
80+ var cleanValue = this . _cleanValue ( value , mask . allowedChars ) ;
81+
82+ // Apply the mask
83+ var maskedValue = this . _applyMaskPattern ( cleanValue , mask ) ;
84+
85+ // Update the field value
86+ if ( maskedValue !== value ) {
87+ g_form . setValue ( fieldName , maskedValue , maskedValue ) ;
88+ }
89+
90+ // Apply visual treatment for sensitive fields
91+ if ( mask . sensitive ) {
92+ this . _applySensitiveFieldTreatment ( fieldName ) ;
93+ }
94+ } ,
95+
96+ _getMaskType : function ( fieldName ) {
97+ // Check for mask type from field attributes
98+ var maskType = g_form . getValue ( fieldName + '_mask_type' ) ;
99+ if ( this . masks [ maskType ] ) {
100+ return maskType ;
101+ }
102+
103+ // Auto-detect based on field name
104+ var fieldLower = fieldName . toLowerCase ( ) ;
105+ if ( fieldLower . includes ( 'phone' ) ) return 'phone' ;
106+ if ( fieldLower . includes ( 'ssn' ) ) return 'ssn' ;
107+ if ( fieldLower . includes ( 'credit' ) || fieldLower . includes ( 'card' ) ) return 'creditCard' ;
108+ if ( fieldLower . includes ( 'date' ) ) return 'date' ;
109+ if ( fieldLower . includes ( 'currency' ) || fieldLower . includes ( 'price' ) ) return 'currency' ;
110+ if ( fieldLower . includes ( 'ip' ) ) return 'ipAddress' ;
111+
112+ return null ;
113+ } ,
114+
115+ _setupField : function ( fieldName , maskType ) {
116+ var mask = this . masks [ maskType ] ;
117+ if ( ! mask ) return ;
118+
119+ // Set placeholder text
120+ g_form . setPlaceholder ( fieldName , mask . pattern . replace ( / # / g, mask . placeholder ) ) ;
121+
122+ // Add visual indicator for sensitive fields
123+ if ( mask . sensitive ) {
124+ this . _applySensitiveFieldTreatment ( fieldName ) ;
125+ }
126+
127+ // Apply initial mask if value exists
128+ var currentValue = g_form . getValue ( fieldName ) ;
129+ if ( currentValue ) {
130+ this . applyMask ( fieldName , currentValue ) ;
131+ }
132+ } ,
133+
134+ _cleanValue : function ( value , allowedChars ) {
135+ return value . split ( '' ) . filter ( function ( char ) {
136+ return allowedChars . test ( char ) ;
137+ } ) . join ( '' ) ;
138+ } ,
139+
140+ _applyMaskPattern : function ( value , mask ) {
141+ var result = mask . pattern ;
142+ var valueIndex = 0 ;
143+
144+ // Replace # in pattern with actual values
145+ for ( var i = 0 ; i < result . length && valueIndex < value . length ; i ++ ) {
146+ if ( result [ i ] === '#' ) {
147+ result = result . substr ( 0 , i ) + value [ valueIndex ++ ] + result . substr ( i + 1 ) ;
148+ }
149+ }
150+
151+ // Replace remaining # with placeholder
152+ result = result . replace ( / # / g, mask . placeholder ) ;
153+
154+ return result ;
155+ } ,
156+
157+ _applySensitiveFieldTreatment : function ( fieldName ) {
158+ // Add sensitive field styling
159+ var element = g_form . getElement ( fieldName ) ;
160+ if ( element ) {
161+ element . addClassName ( 'sensitive-field' ) ;
162+
163+ // Add eye icon to toggle visibility
164+ var container = element . up ( ) ;
165+ if ( ! container . down ( '.toggle-sensitive' ) ) {
166+ var toggle = new Element ( 'span' , {
167+ 'class' : 'toggle-sensitive icon-eye' ,
168+ 'title' : 'Toggle field visibility'
169+ } ) ;
170+ toggle . observe ( 'click' , function ( ) {
171+ this . _toggleSensitiveField ( fieldName ) ;
172+ } . bind ( this ) ) ;
173+ container . insert ( toggle ) ;
174+ }
175+ }
176+ } ,
177+
178+ _toggleSensitiveField : function ( fieldName ) {
179+ var element = g_form . getElement ( fieldName ) ;
180+ if ( element ) {
181+ var isHidden = element . hasClassName ( 'mask-sensitive' ) ;
182+ element . toggleClassName ( 'mask-sensitive' ) ;
183+
184+ var toggle = element . up ( ) . down ( '.toggle-sensitive' ) ;
185+ if ( toggle ) {
186+ toggle . title = isHidden ? 'Hide sensitive data' : 'Show sensitive data' ;
187+ toggle . toggleClassName ( 'icon-eye' ) ;
188+ toggle . toggleClassName ( 'icon-eye-slash' ) ;
189+ }
190+ }
191+ } ,
192+
193+ type : 'FormFieldMasker'
194+ } ;
0 commit comments