Rob van der Woude's Scripting Pages
Powered by GeSHi

PDF Interactive Forms Test

A recent project was creating an interactive PDF conference registration form for a non-profit organization.
Up till then they used a non-interactive PDF that members/attendants had to print, fill in with a pen, and either scan and e-mail or send by snail mail.
Due to the members/attendants' high average age there was some fear that withe the new interactive form we might be spending many hours on support calls.

That is why I wrote a simple "PDF Form Test", allowing members to check if their software is capable of handling PDF forms at all, and if not explaining them to use the old print-pen-snail mail technique.
It was created using PDFill PDF Form Maker.
Initially, it will show the following text:

You cannot fill in interactive PDF forms with the current computer, software and settings.

Use alternative software or change your software's settings, or print the form on paper and send (a scan of) the completed paper form by mail.

If the PDF reader is capable of handling Adobe JavaScript, however, this text is immediately replaced by the following text (with the actual software name and version), and a hidden "Print" button is made visible:

Congratulations!
You are using PDF-XChange Editor version 10.1.3.383.
This software can be used to fill in interactieve PDF forms without restrictions.

Click the "Print" button to send these test results to a printer.

 

Though not visible in the normal view, some extra debugging info will be included in the printed output:

 

Adobe Reader printed output PDF-XChange Editor printed output

 

The code to achieve this is executed when the document is opened:

 

  1. var debugmsg = "";
  2. var newmsg = "";
  3. var viewername = "an unknown program";
  4. var viewerver = "";
  5. var advforms = false;
  6.  
  7. if ( typeof app.viewerType != "undefined" )
  8. {
  9. 	debugmsg += "app.viewerType         = " + app.viewerType;
  10. 	debugmsg += "\napp.viewerVersion      = " + app.viewerVersion;
  11. 	if ( typeof app.pxceInfo != "undefined" )
  12. 	{
  13. 		debugmsg += "\napp.pxceInfo.name      = " + app.pxceInfo.name;
  14. 		debugmsg += "\napp.pxceInfo.variation = " + app.pxceInfo.variation;
  15. 		debugmsg += "\napp.pxceInfo.platform  = " + app.pxceInfo.platform;
  16. 		debugmsg += "\napp.pxceInfo.version   = " + app.pxceInfo.version.join( "." );
  17. 		debugmsg += "\napp.pxceVersion        = " + app.pxceVersion.join( "." );
  18. 	}
  19. 	if ( typeof app.isFoxit != "undefined" )
  20. 	{
  21. 		debugmsg += "\napp.isFoxit           = " + app.isFoxit;
  22. 	}
  23. 	if ( typeof app.plugIns != "undefined" )
  24. 	{
  25. 		var plugins = app.plugIns.join( "\n                         " ); // 25 tabs to align plugins
  26. 		if ( plugins == "" )
  27. 		{
  28. 			plugins = "none";
  29. 		}
  30. 		debugmsg += "\napp.plugIns            = " + plugins;
  31. 	}
  32.  
  33. 	if ( app.viewerType == "Exchange" )
  34. 	{
  35. 		viewername = "Acrobat Standard";
  36. 		advforms = true;
  37. 		viewerver = " version " + app.viewerVersion;
  38. 	}
  39. 	else if ( app.viewerType == "Exchange-Pro" )
  40. 	{
  41. 		viewername = "Acrobat Pro, Foxit PDF Reader or PDF-XChange, or other software spoofing as Acrobat Pro";
  42. 		advforms = true;
  43. 		viewerver = " version " + app.viewerVersion;
  44. 		if ( typeof app.pxceInfo != "undefined" )
  45. 		{
  46. 			viewername = "PDF-XChange " + app.pxceInfo.name;
  47. 			viewerver = " version " + app.pxceInfo.version.join( "." );
  48. 		}
  49. 		else if ( typeof app.isFoxit != "undefined" )
  50. 		{
  51. 			if ( app.isFoxit.indexOf( "Foxit" ) > -1 )
  52. 			{
  53. 				viewername = app.isFoxit;
  54. 			}
  55. 		}
  56. 		else if ( typeof app.plugIns != "undefined" )
  57. 		{
  58. 			if ( app.plugIns.join( ).indexOf( "ADBE" ) > -1 )
  59. 			{
  60. 				viewername = "Acrobat Pro";
  61. 			}
  62. 		}
  63. 	}
  64. 	else if ( app.viewerType == "eXPertPDF" )
  65. 	{
  66. 		viewername = "VisageSoft Expert PDF Reader";
  67. 		viewerver = " version " + app.viewerVersion;
  68. 	}
  69. 	else if ( app.viewerType == "Nitro-Reader" )
  70. 	{
  71. 		viewername = "Nitro PDF Reader";
  72. 		advforms = true;
  73. 		viewerver = app.viewerVersion;
  74. 	}
  75. 	else if ( app.viewerType == "Reader" )
  76. 	{
  77. 		viewername = "Adobe Reader";
  78. 		advforms = true;
  79. 		viewerver = " version " + app.viewerVersion;
  80. 	}
  81. 	else if ( app.viewerType == "PDF.js" )
  82. 	{
  83. 		viewername = "Mozilla Firefox";
  84. 		viewerver = " version " + app.viewerVersion;
  85. 	}
  86. 	else if ( app.viewerType == "pdfium" )
  87. 	{
  88. 		viewername = "Brave, Chrome, Edge, Opera, or another browser";
  89. 		viewerver = " version " + app.viewerVersion;
  90. 	}
  91.  
  92. 	if ( advforms )
  93. 	{
  94. 		newmsg += "Congratulations!\n";
  95. 	}
  96.  
  97. 	newmsg += "You are using " + viewername + viewerver + ".\n";
  98. 	if ( advforms )
  99. 	{
  100. 		newmsg += "This software can be used to fill in interactieve PDF forms without restrictions.\n\n";
  101. 	}
  102. 	else
  103. 	{
  104. 		newmsg += "This software can be used to fill in basic interactieve PDF forms with some restrictions, i.e. calculations will most likely contain errors.\n";
  105. 		newmsg += "Using alternative software that is capable of performing calculations is recommended.\n\n";
  106. 	}
  107. 	newmsg += "Click the \"Print\" button to send these test results to a printer.";
  108. 	this.getField( "Result" ).value = newmsg;
  109. 	this.getField( "DebugHeader" ).display = display.noView; // hidden in normal view, but visible on printout
  110. 	this.getField( "DebugResult" ).display = display.noView;
  111. 	this.getField( "DebugResult" ).value = debugmsg;
  112. 	this.getField( "Button" ).display = display.noPrint; // visible but not printed
  113. }

 

Notes: 1: The test is not 100% reliable on smartphones, some "unknown" PDF viewer apps may still display an empty form.
  2: Saving the test results as PDF is of no use, since it will remain an interactive PDF showing the results for the computer that opens the saved file.
That is why I chose to use a "Print" button: with a PDF printer you can still save the results as a "static" PDF file.

 

The download contains both English and Dutch test PDFs, and the PDFill project files as well, allowing you to modify the files yourself (e.g. translate into other languages?)

Download PDF Form Test

 

Detect PDF Viewer

Some objects available in JavaScript to try and detect the exact PDF Viewer program:

 

JavaScript Returns Application Form Fill Capabilities Remarks
app.viewerType Exchange Acrobat Standard Good  
Exchange-Pro Acrobat Pro, Foxit PDF Reader, PDF-XChange Editor Good Though of little use to detect the exact viewer, still useful to check if the viewer is capable of handling forms
eXPertPDF VisageSoft Expert PDF Reader Limited  
Nitro-Reader Nitro PDF Reader Good  
Reader Adobe Reader Good  
PDF.js Mozilla Firefox Limited  
pdfium Brave, Chrome, Edge, Opera, other browsers Limited  
app.viewerVersion version
(string)
    Viewers that spoof their app.viewerType value (e.g. Foxit, PDF-XChange) may also spoof their app.viewerVersion value
app.pxceInfo.name Editor PDF-XChange Editor Good Available in PDF-XChange only, use if ( typeof app.pxceInfo != 'undefined' ) { ... } to prevent the script from crashing in non-PDF-XChange viewers.
app.pxceVersion returns an array of four numbers that represent the Editor version.
app.pxceInfo returns an object with properties version (identical to app.pxceVersion), variation, name, and platform.
app.pxceVersion version
(array)
   
app.pxceVersion.join('.') version
(string)
   
app.isFoxit foxit name and version Foxit PDF Viewer Good Available in Foxit PDF Viewer only, use
if ( typeof app.isFoxit != 'undefined' ) {
    if ( app.isFoxit.indexOf( "Foxit" ) > -1 ) { ... }
}

to prevent the script from crashing in non-Foxit viewers
app.plugIns.join().indexOf('ADBE') > -1 true if Adobe software Adobe Reader, Acrobat Standard, Acrobat Pro Good Available in Adobe, Foxit and PDF-XChange software, but not in browsers and file managers, use if ( typeof app.plugIns != 'undefined' ) { ... } to prevent the script from crashing in browsers and file managers

 

Note: PDF viewers that do not support JavaScript (e.g. Slim PDF Reader, SumatraPDF), or that don't support the app.viewerType object (e.g. Javelin PDF Reader) cannot be identified, of course.
That is why the PDFFormTest PDF by default states that the viewer cannot be used to fill in forms, and if JavaScript and the app.viewerType object are supported, it will overwrite that statement.

page last modified: 2024-01-04; loaded in 0.0047 seconds