@@ -40,6 +40,123 @@ const FORMAT_DEFAULT = {
4040 } ,
4141} ;
4242
43+ function mapTypeAndFlags ( type , userOptions , pdfObject ) {
44+ let flags = userOptions . Ff ?? 0 ;
45+
46+ if ( type === 'text' ) {
47+ pdfObject . FT = 'Tx' ;
48+ } else if ( type === 'pushButton' ) {
49+ pdfObject . FT = 'Btn' ;
50+ flags |= FIELD_FLAGS . pushButton ;
51+ } else if ( type === 'radioButton' ) {
52+ pdfObject . FT = 'Btn' ;
53+ flags |= FIELD_FLAGS . radioButton ;
54+ } else if ( type === 'checkbox' ) {
55+ pdfObject . FT = 'Btn' ;
56+ } else if ( type === 'combo' ) {
57+ pdfObject . FT = 'Ch' ;
58+ flags |= FIELD_FLAGS . combo ;
59+ } else if ( type === 'list' ) {
60+ pdfObject . FT = 'Ch' ;
61+ } else if ( type ) {
62+ throw new Error ( `Invalid form annotation type '${ type } '` ) ;
63+ }
64+
65+ Object . keys ( userOptions ) . forEach ( ( key ) => {
66+ if ( FIELD_FLAGS [ key ] && userOptions [ key ] ) {
67+ flags |= FIELD_FLAGS [ key ] ;
68+ }
69+ } ) ;
70+
71+ if ( flags !== 0 ) {
72+ pdfObject . Ff = flags ;
73+ }
74+ }
75+
76+ function mapJustify ( userOptions , pdfObject ) {
77+ const result = FIELD_JUSTIFY [ userOptions . align ] ;
78+ if ( typeof result === 'number' && result !== 0 ) {
79+ pdfObject . Q = result ;
80+ }
81+ }
82+
83+ function mapStrings ( options , pdfObject ) {
84+ if ( Array . isArray ( options . select ) && options . select . length ) {
85+ pdfObject . Opt = options . select . map ( ( s ) => {
86+ if ( typeof s === 'string' ) {
87+ return new String ( s ) ;
88+ }
89+ return s ;
90+ } ) ;
91+ }
92+
93+ Object . keys ( VALUE_MAP ) . forEach ( ( key ) => {
94+ if ( key in options ) {
95+ const value = options [ key ] ?? '' ;
96+ pdfObject [ VALUE_MAP [ key ] ] =
97+ typeof value === 'string' ? new String ( value ) : value ;
98+ }
99+ } ) ;
100+
101+ if ( options . MK ?. CA ) {
102+ pdfObject . MK = { CA : new String ( options . MK . CA ) } ;
103+ }
104+
105+ if ( options . label ) {
106+ pdfObject . MK = options . MK ?? { } ;
107+ pdfObject . MK . CA = new String ( options . label ) ;
108+ }
109+ }
110+
111+ function mapFormat ( options , pdfObject ) {
112+ const f = options . format ;
113+ if ( f ?. type ) {
114+ let fnKeystroke ;
115+ let fnFormat ;
116+ let params = '' ;
117+ if ( FORMAT_SPECIAL [ f . type ] !== undefined ) {
118+ fnKeystroke = `AFSpecial_Keystroke` ;
119+ fnFormat = `AFSpecial_Format` ;
120+ params = FORMAT_SPECIAL [ f . type ] ;
121+ } else {
122+ let format = f . type . charAt ( 0 ) . toUpperCase ( ) + f . type . slice ( 1 ) ;
123+ fnKeystroke = `AF${ format } _Keystroke` ;
124+ fnFormat = `AF${ format } _Format` ;
125+
126+ if ( f . type === 'date' ) {
127+ fnKeystroke += 'Ex' ;
128+ params = String ( f . param ) ;
129+ } else if ( f . type === 'time' ) {
130+ params = String ( f . param ) ;
131+ } else if ( f . type === 'number' ) {
132+ let p = Object . assign ( { } , FORMAT_DEFAULT . number , f ) ;
133+ params = String (
134+ [
135+ String ( p . nDec ) ,
136+ p . sepComma ? '0' : '1' ,
137+ '"' + p . negStyle + '"' ,
138+ 'null' ,
139+ '"' + p . currency + '"' ,
140+ String ( p . currencyPrepend ) ,
141+ ] . join ( ',' ) ,
142+ ) ;
143+ } else if ( f . type === 'percent' ) {
144+ let p = Object . assign ( { } , FORMAT_DEFAULT . percent , f ) ;
145+ params = String ( [ String ( p . nDec ) , p . sepComma ? '0' : '1' ] . join ( ',' ) ) ;
146+ }
147+ }
148+ pdfObject . AA = options . AA ?? { } ;
149+ pdfObject . AA . K = {
150+ S : 'JavaScript' ,
151+ JS : new String ( `${ fnKeystroke } (${ params } );` ) ,
152+ } ;
153+ pdfObject . AA . F = {
154+ S : 'JavaScript' ,
155+ JS : new String ( `${ fnFormat } (${ params } );` ) ,
156+ } ;
157+ }
158+ }
159+
43160export default {
44161 /**
45162 * Must call if adding AcroForms to a document. Must also call font() before
@@ -184,209 +301,55 @@ export default {
184301 'Call document.initForm() method before adding form elements to document' ,
185302 ) ;
186303 }
187- let opts = Object . assign ( { } , options ) ;
188- if ( type !== null ) {
189- opts = this . _resolveType ( type , options ) ;
190- }
191- opts = this . _resolveFlags ( opts ) ;
192- opts = this . _resolveJustify ( opts ) ;
193- opts = this . _resolveFont ( opts ) ;
194- opts = this . _resolveStrings ( opts ) ;
195- opts = this . _resolveColors ( opts ) ;
196- opts = this . _resolveFormat ( opts ) ;
197- opts . T = new String ( name ) ;
198- if ( opts . parent ) {
199- opts . Parent = opts . parent ;
200- delete opts . parent ;
201- }
202- return opts ;
203- } ,
304+ const pdfObject = { } ;
204305
205- _resolveType ( type , opts ) {
206- if ( type === 'text' ) {
207- opts . FT = 'Tx' ;
208- } else if ( type === 'pushButton' ) {
209- opts . FT = 'Btn' ;
210- opts . pushButton = true ;
211- } else if ( type === 'radioButton' ) {
212- opts . FT = 'Btn' ;
213- opts . radioButton = true ;
214- } else if ( type === 'checkbox' ) {
215- opts . FT = 'Btn' ;
216- } else if ( type === 'combo' ) {
217- opts . FT = 'Ch' ;
218- opts . combo = true ;
219- } else if ( type === 'list' ) {
220- opts . FT = 'Ch' ;
221- } else {
222- throw new Error ( `Invalid form annotation type '${ type } '` ) ;
223- }
224- return opts ;
225- } ,
306+ mapTypeAndFlags ( type , options , pdfObject ) ;
307+ mapJustify ( options , pdfObject ) ;
308+ this . _mapFont ( options , pdfObject ) ;
309+ mapStrings ( options , pdfObject ) ;
310+ this . _mapColors ( options , pdfObject ) ;
311+ mapFormat ( options , pdfObject ) ;
226312
227- _resolveFormat ( opts ) {
228- const f = opts . format ;
229- if ( f && f . type ) {
230- let fnKeystroke ;
231- let fnFormat ;
232- let params = '' ;
233- if ( FORMAT_SPECIAL [ f . type ] !== undefined ) {
234- fnKeystroke = `AFSpecial_Keystroke` ;
235- fnFormat = `AFSpecial_Format` ;
236- params = FORMAT_SPECIAL [ f . type ] ;
237- } else {
238- let format = f . type . charAt ( 0 ) . toUpperCase ( ) + f . type . slice ( 1 ) ;
239- fnKeystroke = `AF${ format } _Keystroke` ;
240- fnFormat = `AF${ format } _Format` ;
241-
242- if ( f . type === 'date' ) {
243- fnKeystroke += 'Ex' ;
244- params = String ( f . param ) ;
245- } else if ( f . type === 'time' ) {
246- params = String ( f . param ) ;
247- } else if ( f . type === 'number' ) {
248- let p = Object . assign ( { } , FORMAT_DEFAULT . number , f ) ;
249- params = String (
250- [
251- String ( p . nDec ) ,
252- p . sepComma ? '0' : '1' ,
253- '"' + p . negStyle + '"' ,
254- 'null' ,
255- '"' + p . currency + '"' ,
256- String ( p . currencyPrepend ) ,
257- ] . join ( ',' ) ,
258- ) ;
259- } else if ( f . type === 'percent' ) {
260- let p = Object . assign ( { } , FORMAT_DEFAULT . percent , f ) ;
261- params = String ( [ String ( p . nDec ) , p . sepComma ? '0' : '1' ] . join ( ',' ) ) ;
262- }
263- }
264- opts . AA = opts . AA ? opts . AA : { } ;
265- opts . AA . K = {
266- S : 'JavaScript' ,
267- JS : new String ( `${ fnKeystroke } (${ params } );` ) ,
268- } ;
269- opts . AA . F = {
270- S : 'JavaScript' ,
271- JS : new String ( `${ fnFormat } (${ params } );` ) ,
272- } ;
273- }
274- delete opts . format ;
275- return opts ;
276- } ,
313+ pdfObject . T = new String ( name ) ;
277314
278- _resolveColors ( opts ) {
279- let color = this . _normalizeColor ( opts . backgroundColor ) ;
280- if ( color ) {
281- if ( ! opts . MK ) {
282- opts . MK = { } ;
283- }
284- opts . MK . BG = color ;
285- }
286- color = this . _normalizeColor ( opts . borderColor ) ;
287- if ( color ) {
288- if ( ! opts . MK ) {
289- opts . MK = { } ;
290- }
291- opts . MK . BC = color ;
315+ if ( options . parent ) {
316+ pdfObject . Parent = options . parent ;
292317 }
293- delete opts . backgroundColor ;
294- delete opts . borderColor ;
295- return opts ;
318+ return pdfObject ;
296319 } ,
297320
298- _resolveFlags ( options ) {
299- let result = 0 ;
300- Object . keys ( options ) . forEach ( ( key ) => {
301- if ( FIELD_FLAGS [ key ] ) {
302- if ( options [ key ] ) {
303- result |= FIELD_FLAGS [ key ] ;
304- }
305- delete options [ key ] ;
306- }
307- } ) ;
308- if ( result !== 0 ) {
309- options . Ff = options . Ff ? options . Ff : 0 ;
310- options . Ff |= result ;
321+ _mapColors ( options , pdfObject ) {
322+ let color = this . _normalizeColor ( options . backgroundColor ) ;
323+ if ( color ) {
324+ pdfObject . MK = pdfObject . MK ? pdfObject . MK : { } ;
325+ pdfObject . MK . BG = color ;
311326 }
312- return options ;
313- } ,
314327
315- _resolveJustify ( options ) {
316- let result = 0 ;
317- if ( options . align !== undefined ) {
318- if ( typeof FIELD_JUSTIFY [ options . align ] === 'number' ) {
319- result = FIELD_JUSTIFY [ options . align ] ;
328+ color = this . _normalizeColor ( options . borderColor ) ;
329+ if ( color ) {
330+ if ( ! pdfObject . MK ) {
331+ pdfObject . MK = { } ;
320332 }
321- delete options . align ;
322- }
323- if ( result !== 0 ) {
324- options . Q = result ; // default
333+ pdfObject . MK . BC = color ;
325334 }
326- return options ;
327335 } ,
328336
329- _resolveFont ( options ) {
337+ _mapFont ( options , pdfObject ) {
338+ const { _acroform, _font } = this ;
330339 // add current font to document-level AcroForm dict if necessary
331- if ( this . _acroform . fonts [ this . _font . id ] == null ) {
332- this . _acroform . fonts [ this . _font . id ] = this . _font . ref ( ) ;
340+ if ( _acroform . fonts [ _font . id ] == null ) {
341+ _acroform . fonts [ _font . id ] = _font . ref ( ) ;
333342 }
334343
335344 // add current font to field's resource dict (RD) if not the default acroform font
336- if ( this . _acroform . defaultFont !== this . _font . name ) {
337- options . DR = { Font : { } } ;
345+ if ( _acroform . defaultFont !== _font . name ) {
346+ pdfObject . DR = { Font : { } } ;
338347
339348 // Get the fontSize option. If not set use auto sizing
340349 const fontSize = options . fontSize || 0 ;
341350
342- options . DR . Font [ this . _font . id ] = this . _font . ref ( ) ;
343- options . DA = new String ( `/${ this . _font . id } ${ fontSize } Tf 0 g` ) ;
344- }
345- return options ;
346- } ,
347-
348- _resolveStrings ( options ) {
349- let select = [ ] ;
350- function appendChoices ( a ) {
351- if ( Array . isArray ( a ) ) {
352- for ( let idx = 0 ; idx < a . length ; idx ++ ) {
353- if ( typeof a [ idx ] === 'string' ) {
354- select . push ( new String ( a [ idx ] ) ) ;
355- } else {
356- select . push ( a [ idx ] ) ;
357- }
358- }
359- }
360- }
361- appendChoices ( options . Opt ) ;
362- if ( options . select ) {
363- appendChoices ( options . select ) ;
364- delete options . select ;
365- }
366- if ( select . length ) {
367- options . Opt = select ;
368- }
369-
370- Object . keys ( VALUE_MAP ) . forEach ( ( key ) => {
371- if ( options [ key ] !== undefined ) {
372- options [ VALUE_MAP [ key ] ] = options [ key ] ;
373- delete options [ key ] ;
374- }
375- } ) ;
376- [ 'V' , 'DV' ] . forEach ( ( key ) => {
377- if ( typeof options [ key ] === 'string' ) {
378- options [ key ] = new String ( options [ key ] ) ;
379- }
380- } ) ;
381-
382- if ( options . MK && options . MK . CA ) {
383- options . MK . CA = new String ( options . MK . CA ) ;
384- }
385- if ( options . label ) {
386- options . MK = options . MK ? options . MK : { } ;
387- options . MK . CA = new String ( options . label ) ;
388- delete options . label ;
351+ pdfObject . DR . Font [ _font . id ] = _font . ref ( ) ;
352+ pdfObject . DA = new String ( `/${ _font . id } ${ fontSize } Tf 0 g` ) ;
389353 }
390- return options ;
391354 } ,
392355} ;
0 commit comments