Skip to main content
Participant
December 5, 2024
Answered

app.execDialog method's dialog box validate, commit, and ItemID handlers do not behave as documented

  • December 5, 2024
  • 2 replies
  • 645 views

I am trying to create a dialog box for use in a Dynamic Stamp and the app.execDialog method's dialog box validate, commit, and ItemID handlers do not behave as documented.

 

I am using Adobe Acrobat Pro Continuous Release Version 2024.004.20272 (24.4.20272.0) and am following the guidelines in the Adobe JavaScript APIs reference, https://opensource.adobe.com/dc-acrobat-sdk-docs/library/jsapiref/JS_API_AcroJS.html#execdialog

 

The initialize handler is called when the dialog box is being initialized, and the destroy handler is called when the Cancel button is clicked, as expected, however, the validate, commit, and ItemID handlers do not work as described.

 

For example:

  • The validate handler is not called when a field is modified, though it does get called when the Ok button is clicked.
  • The commit and ok handlers are not called when the Ok button is clicked.
  • The ItemID handler is not called when the edit_text boxes lose focus.
  • The only way to close the dialog box is to click the Cancel button, but I expected the Ok button to also exit the dialog box.
  • Finally, the API reference does not specify an ok handler, however, Example 2 in the reference shows an ok handler, which also does not work.

 

Here is my test procedure and the results:

  1. Open the JavaScript console.
  2. Copy and paste the script into the console.
  3. Press <CTRL>-A to select all and press <CTRL>-<ENTER> to execute the script.
    • "Initializing!" is printed to the console, as expected.
  4.  Type some text into the fname edit_text box.
  5. Press <TAB> to change the focus to the lname edit_text box.
    • Nothing is printed to the console. I expected to see "Modifying ItemID!"
  6. Type some text into the lnam edit_text box.
  7. Press <TAB> to change the focus to the Ok button.
    • Nothing is printed to the console. I expected to see "Modifying ItemID!"
  8. Press <ENTER> to click the OK button.
    • "Validating!" is printed to the console. I expected to see "Commiting!" and possibly "OKing!"
  9. Press <ENTER> to click the OK button again .
    • "Validating!" is printded to the console. I expected to see "Commiting!" and possibly "OKing!"
  10. Use the mouse to click the OK button again.
    • "Validating!" is printed to the console. I expected to see "Commiting!" and possibly "OKing!"
  11. Press <TAB> to change the focus to the Cancel button.
    • Nothing is printed to the console. I expected to see "Modifying ItemID!"
  12.  Press <ENTER> to click the Cancel button.
    • "Destroying!" is printed to the console, and the diolog window is closed, then "cancel" and "true" are also printed to the console, as expected.

 

Here is my script which demonstrates the issues:

var dialog1 = {
    initialize: function(dialog)
    {
        // Called when the dialog box is being initialized.
        console.println("Initializing!");
    },
    validate: function(dialog)
    {
        // Called when a field is modified to determine if the value is
        // acceptable (returning true) or unacceptable (returning false).
        console.println("Validating!");
    },
    commit: function(dialog)
    {
        // Called when the OK button of dialog box is clicked.
        console.println("Committing!");
    },
    ok: function(dialog)
    {
        // Called after commit when the OK button of dialog box is clicked.
        console.println("OKing!");
    },
    destroy: function(dialog)
    {
        // Called when the dialog box is being destroyed.
        console.println("Destroying!");
    },
    ItemID: function(dialog)
    {
        // Called when the dialog box element ItemID is modified.
        // For a text box, it is when the text box loses focus.
        console.println("Modifying ItemID!");
    },
    description:
    {
        type: "cluster",
        name: "Main Dialog",
        align_children: "align_left",
        item_id: "main",
        first_tab: "fnam",
        elements: [
            {
                type: "view",
                align_children: "align_row",
                elements: [
                    {
                        type: "static_text",
                        name: "First Name: "
                    },
                    {
                        item_id: "fnam",
                        next_tab: "lnam",
                        type: "edit_text",
                        alignment: "align_fill",
                        width: 300,
                        height: 20
                    }
                ]
            },
            {
                type: "view",
                align_children: "align_row",
                elements: [
                    {
                        type: "static_text",
                        name: "Last Name: "
                    },
                    {
                        item_id: "lnam",
                        next_tab: "ok",
                        type: "edit_text",
                        alignment: "align_fill",
                        width: 300,
                        height: 20
                    }
                ]
            },
            {
                item_id: "ok",
                next_tab: "fnam",
                type: "ok_cancel",
                alignment: "align_right",
                ok_name: "Ok",
                cancel_name: "Cancel"
            }
        ]
    }
};

console.println(app.execDialog(dialog1));

 

I am new to Adobe JavaScript programming.  I was able to create a dynamic stamp using the app.response() and the app.popUpMenuEx() methods, however, the stamp requires 10 user inputs so now I am trying to use the app.execDialog() method to consolidate all the user input into a single dialog.  Any insight would be greatly appreciated.

This topic has been closed for replies.
Correct answer try67

You're right, the documentation is very lacking and sometimes just flat out wrong.

Here are my corrections to it:

* validate: this method is called just before the dialog is committed. It can be used to accept or reject the user's values, by returning true or false, respectively. If false is returned, the dialog is not closed.

* commit and ok are called when the ok button is clicked, but only if it passes validation (ie. if the validate method returns true, or if it doesn't exist at all)

* ItemID methods: You misunderstood how it is called, but it's also not documented correctly. The name of the function needs to be the actual 4-character item_id value of the field, so "fnam" or "lnam" in your case.

This function is called when the value of the corresponding field has changed. For text fields, this means the user entered them, modified their value, then exited them. Entering and exiting a text field without modifying its value does not trigger its associated function. For all other types of fields it is triggered by any interaction that changes the value.

* ok handler: this does work, but is not really needed, since it is covered by the return value of the dialog object. When the user clicks OK the dialog is validated, then committed, then a return value is returned that matches the button that was used to close it, in this case "ok". If "Cancel" is clicked the dialog is destroyed and "cancel" is returned.

 

I modified your code to make the progression of events more clear by using alerts instead of the console. Try this version of it:

 

 

 

var dialog1 = {
    initialize: function(dialog)
    {
        // Called when the dialog box is being initialized.
        app.alert("Initializing!");
    },
    validate: function(dialog)
    {
        // Called when a field is modified to determine if the value is
        // acceptable (returning true) or unacceptable (returning false).
        app.alert("Validating!");
		return dialog.store()["fnam"]!="";
    },
    commit: function(dialog)
    {
        // Called when the OK button of dialog box is clicked.
        app.alert("Committing!");
    },
    ok: function(dialog)
    {
        // Called after commit when the OK button of dialog box is clicked.
        app.alert("OKing!");
    },
    destroy: function(dialog)
    {
        // Called when the dialog box is being destroyed.
        app.alert("Destroying!");
    },
	fnam: function(dialog) {
		// Called when the value of the fnam field is modified
		app.alert("fnam");
	},
    description:
    {
        type: "cluster",
        name: "Main Dialog",
        align_children: "align_left",
        item_id: "main",
        first_tab: "fnam",
        elements: [
            {
                type: "view",
                align_children: "align_row",
                elements: [
                    {
                        type: "static_text",
                        name: "First Name: "
                    },
                    {
                        item_id: "fnam",
                        next_tab: "lnam",
                        type: "edit_text",
                        alignment: "align_fill",
                        width: 300,
                        height: 20
                    }
                ]
            },
            {
                type: "view",
                align_children: "align_row",
                elements: [
                    {
                        type: "static_text",
                        name: "Last Name: "
                    },
                    {
                        item_id: "lnam",
                        next_tab: "ok",
                        type: "edit_text",
                        alignment: "align_fill",
                        width: 300,
                        height: 20
                    }
                ]
            },
            {
                item_id: "ok",
                next_tab: "fnam",
                type: "ok_cancel",
                alignment: "align_right",
                ok_name: "Ok",
                cancel_name: "Cancel"
            }
        ]
    }
};

app.alert("return value: " + app.execDialog(dialog1));

 

 

 

NB. These are not the only mistakes in the documentation, you'll be happy to hear...

2 replies

try67
Community Expert
try67Community ExpertCorrect answer
Community Expert
December 5, 2024

You're right, the documentation is very lacking and sometimes just flat out wrong.

Here are my corrections to it:

* validate: this method is called just before the dialog is committed. It can be used to accept or reject the user's values, by returning true or false, respectively. If false is returned, the dialog is not closed.

* commit and ok are called when the ok button is clicked, but only if it passes validation (ie. if the validate method returns true, or if it doesn't exist at all)

* ItemID methods: You misunderstood how it is called, but it's also not documented correctly. The name of the function needs to be the actual 4-character item_id value of the field, so "fnam" or "lnam" in your case.

This function is called when the value of the corresponding field has changed. For text fields, this means the user entered them, modified their value, then exited them. Entering and exiting a text field without modifying its value does not trigger its associated function. For all other types of fields it is triggered by any interaction that changes the value.

* ok handler: this does work, but is not really needed, since it is covered by the return value of the dialog object. When the user clicks OK the dialog is validated, then committed, then a return value is returned that matches the button that was used to close it, in this case "ok". If "Cancel" is clicked the dialog is destroyed and "cancel" is returned.

 

I modified your code to make the progression of events more clear by using alerts instead of the console. Try this version of it:

 

 

 

var dialog1 = {
    initialize: function(dialog)
    {
        // Called when the dialog box is being initialized.
        app.alert("Initializing!");
    },
    validate: function(dialog)
    {
        // Called when a field is modified to determine if the value is
        // acceptable (returning true) or unacceptable (returning false).
        app.alert("Validating!");
		return dialog.store()["fnam"]!="";
    },
    commit: function(dialog)
    {
        // Called when the OK button of dialog box is clicked.
        app.alert("Committing!");
    },
    ok: function(dialog)
    {
        // Called after commit when the OK button of dialog box is clicked.
        app.alert("OKing!");
    },
    destroy: function(dialog)
    {
        // Called when the dialog box is being destroyed.
        app.alert("Destroying!");
    },
	fnam: function(dialog) {
		// Called when the value of the fnam field is modified
		app.alert("fnam");
	},
    description:
    {
        type: "cluster",
        name: "Main Dialog",
        align_children: "align_left",
        item_id: "main",
        first_tab: "fnam",
        elements: [
            {
                type: "view",
                align_children: "align_row",
                elements: [
                    {
                        type: "static_text",
                        name: "First Name: "
                    },
                    {
                        item_id: "fnam",
                        next_tab: "lnam",
                        type: "edit_text",
                        alignment: "align_fill",
                        width: 300,
                        height: 20
                    }
                ]
            },
            {
                type: "view",
                align_children: "align_row",
                elements: [
                    {
                        type: "static_text",
                        name: "Last Name: "
                    },
                    {
                        item_id: "lnam",
                        next_tab: "ok",
                        type: "edit_text",
                        alignment: "align_fill",
                        width: 300,
                        height: 20
                    }
                ]
            },
            {
                item_id: "ok",
                next_tab: "fnam",
                type: "ok_cancel",
                alignment: "align_right",
                ok_name: "Ok",
                cancel_name: "Cancel"
            }
        ]
    }
};

app.alert("return value: " + app.execDialog(dialog1));

 

 

 

NB. These are not the only mistakes in the documentation, you'll be happy to hear...

try67
Community Expert
Community Expert
December 5, 2024

PS. I also modified the code so that the First Name field is required and the Last Name field is not. In other words, if you don't fill in the First Name, validation fails and the dialog stays open.

Thom Parker
Community Expert
Community Expert
December 5, 2024

I've been creating Acrobat JavaScript dialogs for years.  The documentation is not as verbose as one would like, but it is acurate. For example the validate handler is only called after the ok button is pushed, not when dialog fields are changed. In fact, the validate handler must return true for the dialog to exit. This is kind of the point of the validate function. If if doesn't return an explicit value, then it returns "undefined", which is interpreted as false, meaning that dialog validation failed. Therefore the dialog doesn't close. 

 

You might find this tool very helpful.

https://www.pdfscripting.com/public/ACRODIALOGS-OVERVIEW.cfm

 

And this page on stamps. 

https://www.pdfscripting.com/public/All_About_PDF_Stamps.cfm

 

Thom Parker - Software Developer at PDFScriptingUse the Acrobat JavaScript Reference early and often
Participant
December 6, 2024

Thanks Thom.  I've read a number of your posts and read and watched your dynamic stamp tutorials, but I had not looked at the dialog tutorials yet.  I'll check them out.

 

After understanding how the execDialog() method works, I can agree the documentation for the ItemID handler is accurate, though it could be better.  I cannot, however, agree that the documentation for the validate and commit handlers are accurate.

  • The validate documentation states "called when a field is modified" but it is actually "called when the OK button of the dialog box is clicked."
  • The commit documentation states "called when the OK button of the dialog box is clicked,"  but it is actually "called when the validate handler returns true."
  • Additionally, the documentation for the ok handler is missing (other than as a comment in Example 2).

 

Thanks for taking the time to answer and for the wealth of resources you have published.

Thom Parker
Community Expert
Community Expert
December 6, 2024

Yeah, after going back and looking it over, the documentation is pretty poor, and not quite right in some places. Not an unusual situation with Acrobat documentation. 

 

Thom Parker - Software Developer at PDFScriptingUse the Acrobat JavaScript Reference early and often