[javascript] easier dynamic stamp creation  SOLVED

Forum for the PDF-XChange Editor - Free and Licensed Versions

Moderators: PDF-XChange Support, Daniel - PDF-XChange, Chris - PDF-XChange, Sean - PDF-XChange, Paul - PDF-XChange, Vasyl - PDF-XChange, Ivan - Tracker Software, Stefan - PDF-XChange

Mathew
User
Posts: 668
Joined: Thu Jun 19, 2014 7:30 pm

[javascript] easier dynamic stamp creation  SOLVED

Post by Mathew »

This tool (library) makes it much easier to add dynamic fields with a dialog to stamps. It also adds functionality to change the color of the stamp elements in the dialog, set the strokeColor or other properties of the stamp after it's placed, and start another menu item immediately after the stamp is placed. It will also save the values entered into fields for the next time you use the stamp.

The color changing functionality takes advantage of the trick that if there are annotation (markup) objects in a stamp, they can be manipulated by a script immediately before the stamp is placed. When the stamp is placed, all these objects get flattened into the stamp by PDF XChange. I've only tested in PDF XChange 10.5.2.


One still needs to go through the usual rigmarole to get the stamp ID, but all of the code for generating the dialog, and filling in form fields, is handled.

Installation
Unzip and save in JavaScripts folder, then restart PDF XChange. You may need to make the folder. Either in
C:\Users\[USERNAME]\AppData\Roaming\Tracker Software\PDFXEditor\3.0\Javascripts
OR so that all users have access:
C:\Program Files\Tracker Software\PDF Editor\Javascripts
xutil.stampUtils v1.7.1.zip

Examples
I've posted some usage examples below in separate posts, included sample stamp sets that make use of this library.
Example 1: Dialog with one field, color picker and auto-increment
Example 2: Multiple form fields, and auto-calculated date field
Example 3: Stamp Properties: Setting stamp subject based on form field value
Example 4: Using form fields and functions to set other properties and stamp colors
Example 5: Adding additional colors to stamps
Example 6: Running scripts before the stamp is placed, and changing properties of annotations in the stamp
Example 7: Weld symbol stamps that start the arrow tool
Example 8: Set color of stamp elements. This example shows all the steps for creating a dynamic stamp.

Usage
Assign a custom action to one of the form fields. For the custom action, call this function.

Code: Select all

xutil.stampDialog( stampID, dialogConstructor[, dialogConstructor, ...])
stampID this is the ID for this stamp
dialogConstructor is an object that has various key:value pairs for each dialog field you want to create. The keys and their acceptable values are as follows:
field: "FieldName" (optional) the form field in the stamp that will be filled from the dialog.
  • FieldName is also the globals key under which the entered value is stored for the next time the stamp is used. If you skip the field parameter, it will create static text from description unless it's a 'button' in which case this parameter is ignored.
  • description: "Field description text" (optional only if there's a field paramenter) If null or omitted it skips the dialog and assigns the default value - use an empty string "" if no description needed.
  • value: "Default value" or function(), (optional assigns "" if omitted)
    For radio, list box or combo box, the format is [item1, item2, ...] The items can either be a string, in which case that is what is both displayed and returned, or an object {value:"code", description:"Text description"} in which case the description is displayed, but the value is returned.
  • type: (optional) type of dialog box item - if omitted gets type from field (check_box, radio, list_box, hier_list_box, static_text, edit_text, popup, button, cluster, view)
  • handler( dialog ): (optional) function to call when the dialog item is clicked or changed.
    Required for type: 'button', where the field parameter is ignored.
    'this' is the dialog monitor and 'dialog' is the dialog object.
    • Note that the dialog monitor is supplied with two properties to help decipher which field maps to which dialog element:
      this.fields is a list of all fields, and their index is the index on the item_id for dialog elements 'db00' is the first, 'db01' second, etc
      this.radios is a list of radio buttons with the value [field, returnValue]; the item_id for radios is 'rd00', 'rd01', etc based on the index in the this.radios; and the group_id is the field item_id from this.fields
  • increment: value (optional) 'value' is either:
    • a number to increment by (ie 1, -2, etc). Increment happens before the dialog is shown; or
    • an array [incVal, format] where 'incVal' is the number to increment by (or zero), and 'format' is one of the following: r,R,c,C,nWidth (roman lowercase, roman uppercase, alphabet lowercase, alphabet uppercase, number of digits)
  • labelWidth: (optional) sets the width of the auto-generated label on edit_text, popup, list_box
  • ok( stamp ): (optional) function to run after the ok button is pressed.
    'stamp' is the current stamp, and 'this' is the current dialogConstructor,
  • globals: for each of the dialogObjects, this is the saved global variables for this stamp, in the form {key:value, ...} where key is the fieldName. It has access to any saved field values for the whole stamp file. It is updated with the information from the dialog box before ok() is run. Note: If using globals to get the values of other fields, field values are updated in globals in the order they are processed, so data for dialogConstructors below the current one will be old (from the previous time the stamp was used)
  • setProp: (optional) stamp property name to set from the value of this field, or {property:value} object to supply the value.
  • (optional) other parameters can be passed to dialog such as 'width', 'height', 'char_width', 'char_height', 'font', 'bold', 'italic', 'alignment', 'multiline', 'multi_select', 'separator:1', 'align_children',etc
The following properties should have their own dialogConstructor objects:
colorX: defaultColor or function()
  • description: "Color Dialog Description", (optional) sets a color picker dialog - if null or omitted then no dialog and it assigns the default color
  • strokeColor: true (optional) to set the strokecolor of the stamp
    To get the color on objects to change, they need to be annotations or fields. Annotation subject or author, and Field Tooltip or Mapping Name must contain the text %colorX TFS% where X is an optional index if there are multiple color pickers and T,F,S is for text, fillcolor or strokeColor is set
    For example: %color S% to set the text and stroke color if there's only one color dialog item
    The globals property will be updated with all current field values before the colors are applied
startTool: "cMenuItem" - runs app.execMenuItem("cMenuItem") after the stamp is placed. If you pass it a function, it will run that function.


The above example will throw a javascript exception if someone with the stamp file is missing xutil.stampUtils.js (ie they only got a copy of the stamp file). I'm not sure why this would happen :wink: , but if you want it to fail gracefully and just act like a static stamp, revise the function call thus:

Code: Select all

    // alternative that checks first if xutil.stampDialog method exists:
    if ("object" === typeof xutil) xutil.stampDialog?.( stampID, dialogConstructor, ... );

Debugging
With the stamp file open, you can run the javascript code in the console to check how it works before pasting it into the custom action for the field. It should open a dialog and fill fields/change colors as it would when the stamp is placed. It will also output any errors it encounters into the console.


Limitations
  • Once a stamp is started, I don't think there's anything a script can do to stop it. I used to have a Cancel button on stamp dialogs, but it couldn't cancel the stamp placement. I started using the cancel button as a "reset" (ie I'd clear all the fields), but it's such a rare occurrence that I need to clear the fields (I can go through and clear them myself before placing the stamp if I absolutely want a blank stamp). So I only show an OK button now.
  • Dynamic stamps relying on this tool must be used on applications able to run this tool! It is not tested on software other than PDF XChange Editor. I didn't use any PXCE special javascript, so it may work on other applications, although they tend to not be as up to date on javascript. Let me know. If it's just a matter of minor tweaks, I'll try to do them. But I'm not willing to re-write it in an earlier version of javascript, for example.

Source Code
The tool is released under the MIT (Expat) license. I post the source code here: viewtopic.php?t=44731
You do not have the required permissions to view the files attached to this post.
Last edited by Mathew on Wed Sep 17, 2025 11:41 pm, edited 42 times in total.
Mathew
User
Posts: 668
Joined: Thu Jun 19, 2014 7:30 pm

Re: [javascript] easier dynamic stamp creation

Post by Mathew »

Usage example 1
Here's a simple example creating a dynamic stamp that has a dialog to enter the current value, with auto-increment on each subsequent use.

  1. The stamp is a hexagon, with one field:
    image.png
  2. On the field I set a Default Value to A so the stamp shows a letter, and I set the Tooltip to %color T% so the text color can be changed
    image(1).png
  3. The hexagon shape is a polygon annotation, and I set the Author to %color S% so only the strokeColor gets changed. You'll need to recreate any content items as annotations if you want the tool to change their color
    image(2).png
  4. Select the field, and under Value Calculation, pick "Custom Action", click on the to enter the code to generate the dialog:

    Code: Select all

    xutil.stampDialog( "#oA9CC7PiJ5cdxB4QH8g7E2", 
    	{ field: "hexagon", description: "Enter value:", value: "A", increment: [ 1, 'C']},
    	{ color: color.red, description: "Color:", strokeColor: true });
Debugging
With the stamp file open, you can run the javascript code in the console to check how it works before pasting it into the custom action for the field. It should open a dialog and fill fields/change colors as it would when the stamp is placed. It will also output any errors it encounters into the console.

Save the file, quit PDF XChange and move the stamp file back into the Stamps folder. This stamp should now have a dialog when placed:
image(5).png

Brief explanation
  • The first item was the stampID
    image(4).png
  • The second item uses the field name, and I gave a default value "A", and increment of 1 using capital letters
  • The third item is a color picker, with default color red (but it will save the last entered color), and the strokeColor: true option so that once the stamp is placed, it will have its stroke color set to whatever color was picked.
Stamps!
Here is a dynamic stamp file with some shapes that have auto-increment and dialogs similar to above
Shapes.pdf
image(3).png
They have a slight variation: I've used a function on the increment so it tries to guess if its incrementing numbers or letters:

Code: Select all

xutil.stampDialog( "#mBl0HFq5t6Y_02DVbBhbM1", 
	{ field: "hexagon", description: "Enter value:", value: "A", increment: function(){
	  let fv = this.globals[this.field] ?? this.value; // current field value
	  let t = isNaN(fv) ? (fv === fv.toUpperCase() ? 'C' : 'c') : ''; // try to guess whether letters or numbers
	  return [1, t]}},
	{ color: color.red, description: "Color:", strokeColor: true });
You do not have the required permissions to view the files attached to this post.
Last edited by Mathew on Fri Aug 01, 2025 11:40 pm, edited 2 times in total.
Mathew
User
Posts: 668
Joined: Thu Jun 19, 2014 7:30 pm

Re: [javascript] easier dynamic stamp creation

Post by Mathew »

Usage Example 2

I shared a dynamic shop drawing stamp in another forum post that relies on pure javascript for the dialog. The example below is how it could be done much more easily with this tool:

The stamp is set up exactly the same:
image.png

The code for the dialog is:

Code: Select all

xutil.stampDialog("#h7ipW9UlS4EWmFqht1B1F2",
{type: 'cluster', description: "Shop Drawing Response", elements:[
  {field: 'revw_NET', description: "No Exception Taken"},
  {field: 'revw_MCN', description: "Make Corrections Noted"},
  {field: 'revw_SSI', description: "Submit Specified Item"},
  {field: 'revw_RR', description: "Revise and Resubmit"},
  {field: 'revw_REJ', description: "Rejected"},
  {field: 'revw_USR', description: {field: 'revw_URES', description:''}},
]},
{description: "Company Name", separator:1},
{field: 'revw_CoNm', description: "", multiline: true, char_height: 3},
{field: 'revw_date', description: "Date: ", value() {return util.printd("mmm d, yyyy", new Date())}},
{field: 'revw_rvBy', description: "By: ", value: identity.name} );
The resulting dialog is:
image(1).png
Explanation
For all the fields, I didn't bother putting in the type property, because I want it to be the same type as the field in the stamp.
There are a few things I added here that make it a bit more complicated:

On line 2 I've added a 'cluster' that is a frame with a title. DialogConstructors are put inside the elements:[ ] array. You can add cluster or view elements to group dialogConstructors together in the final dialog.

On lines 10&11 I've moved the description out of the field descriptor because I want the input field to be full width (not laid out with a label in front like the following two lines). For the field "revw_CoNm" I made the description an empty string "" because I still want the field to show in the dialog (if I'd left it off entirely, no dialog would be created for it). I also set the text field to multiline and gave it a char_height -- could have also just given a height in points -- because by default the height is only one row.

On line 12 I used a function instead of a static value, so that the dialog can auto-fill with today's date.

On line 13 The value assigned is the current user identity name (as entered in PDF XChange), but it's a static value, so that will only be used the first time the stamp is used. Subsequently, it will load the entered name from the previous time the stamp was used.
You do not have the required permissions to view the files attached to this post.
Last edited by Mathew on Fri Apr 11, 2025 11:29 pm, edited 1 time in total.
User avatar
Stefan - PDF-XChange
Site Admin
Posts: 19917
Joined: Mon Jan 12, 2009 8:07 am

Re: [javascript] easier dynamic stamp creation

Post by Stefan - PDF-XChange »

Hello Mathew,

Once again many thanks for your great contributions!

Kind regards,
Stefan
Mathew
User
Posts: 668
Joined: Thu Jun 19, 2014 7:30 pm

Re: [javascript] easier dynamic stamp creation

Post by Mathew »

:D It's gratifying that people find them useful.

Usage Example 3

Stamp properties are normally a static item that's set when the stamp is created. This example shows how to set the stamp's subject to match the information entered in a dialog.

The stamp is an inventory number that the user enters:
image.png
The dialogConstructor is as before, but I add the property setProp: 'subject' to assign the entered value to the stamp subject:

Code: Select all

xutil.stampDialog( "#r1i7kEcaI5gon0NtJ7Zsy3",
{field: 'InvNumber', description: "Inventory Number:", setProp: 'subject'})
The resulting dialog:
image(1).png
Notice that the label for the field gets wrapped because it's too long to fit the default 80px width. Two ways to handle it:
  1. Set the optional property labelWidth to a larger number:

    Code: Select all

    xutil.stampDialog( "#r1i7kEcaI5gon0NtJ7Zsy3",
    {field: 'InvNumber', description: "Inventory Number:", setProp: 'subject', labelWidth: 100})
    image(2).png
  2. Put the label on a separate line and set the InvNumber description to an empty string:

    Code: Select all

    xutil.stampDialog( "#r1i7kEcaI5gon0NtJ7Zsy3",
    {description: "Inventory Number:"},
    {field: 'InvNumber', description: "", setProp: 'subject'})
    image(3).png
The resulting stamp:
image(4).png
and subject:
image(5).png
You do not have the required permissions to view the files attached to this post.
Mathew
User
Posts: 668
Joined: Thu Jun 19, 2014 7:30 pm

Re: [javascript] easier dynamic stamp creation

Post by Mathew »

I publish it and immediately after find bugs. Happens a lot :oops: . Updated to v1.2 above.

Changes in v1.2:
  • allow popup to return a non-string value;
  • add try/catch and better error reporting to setStampProperty
Last edited by Mathew on Fri Aug 22, 2025 1:17 am, edited 1 time in total.
Mathew
User
Posts: 668
Joined: Thu Jun 19, 2014 7:30 pm

Re: [javascript] easier dynamic stamp creation

Post by Mathew »

Another update v1.3 posted above.
  • fix color dialog when function is supplied;
  • remove unnecessary code;
  • move some defaults to front of function;
  • update all fields & globals before color assignment is done

Usage Example 4

The above Example 3 can be further extended to set the stamp's strokeColor to a user assigned color based on a popup that has specific options. In this example, I'll use the following colors as "Tags" and give descriptions of the tags in the dialog:
  • Important (red)
  • Error (orange)
  • Sent (green)
  • Completed (blue)
  • Other (purple)
The dialogConstructor is as follows. Most of the code is setting up the 'popup' with the color values (I'm using both the built-in constant color and the form ['RGB',1,0.5,0] to call out orange for example):

Code: Select all

xutil.stampDialog( "#r1i7kEcaI5gon0NtJ7Zsy3",
{field: 'InvNumber', description: "Inventory Number:", setProp: 'subject', labelWidth: 100},
{field: 'InvTag', description: "Tag as:", type: 'popup', value: [
  {value: color.red, description:"Important"},
  {value: ['RGB',1,0.5,0], description:"Error"},
  {value: color.green, description:"Sent"},
  {value: color.blue, description:"Completed"},
  {value: ['RGB',0.5,0,1], description:"Other"}
  ], setProp: 'strokeColor'})
The last line sets the property 'strokeColor' to whatever value the popup returns.

Resulting dialog:
image.png
Now the stamp will set both the strokeColor and the subject:
Grouping by subject:
image(1).png
or grouping by color:
image(2).png


Example 4a

Using the colorX dialogConstructor, as shown in Example 1, it's quite simple to offer a color picker to change the colors of the stamp. This example does it programmatically, based on the predefined values in the popup. As usual with the colorX dialogConstructor, the linework and text in the stamp must be annotations. Continuing with the same stamp as above:

Set the linework author to %color S%
image(3).png
Set the Text Box annotation "Inv #" author to %color F% to change the fill color behind the text
image(4).png
One more line is needed in the dialogConstructor

Code: Select all

xutil.stampDialog( "#r1i7kEcaI5gon0NtJ7Zsy3",
{field: 'InvNumber', description: "Inventory Number:", setProp: 'subject', labelWidth: 100},
{field: 'InvTag', description: "Tag as:", type: 'popup', value: [
  {value: color.red, description:"Important"},
  {value: ['RGB',1,0.5,0], description:"Error"},
  {value: color.green, description:"Sent"},
  {value: color.blue, description:"Completed"},
  {value: ['RGB',0.5,0,1], description:"Other"}
  ], setProp: 'strokeColor'},
{color() {return this.globals['InvTag']} })
The last line has no description in the constructor object, so no dialog is created. Also, to get the updated field values, it needs to be a function that gets the value of 'InvTag' field when the color is applied. xutil.stampDialog processes all fields and saves their values to the globals before applying colors, so it can access the current field values from globals.

This is the resulting stamp if tagged "Important":
image(5).png
or "Other":
image(6).png
This is the stamp file including for the examples 1 through 4:
examples.pdf
You do not have the required permissions to view the files attached to this post.
Last edited by Mathew on Fri Aug 01, 2025 11:41 pm, edited 2 times in total.
User avatar
Stefan - PDF-XChange
Site Admin
Posts: 19917
Joined: Mon Jan 12, 2009 8:07 am

[javascript] easier dynamic stamp creation

Post by Stefan - PDF-XChange »

:)
Mathew
User
Posts: 668
Joined: Thu Jun 19, 2014 7:30 pm

Re: [javascript] easier dynamic stamp creation

Post by Mathew »

More bug fixes v1.5 posted above.
  • console output if stampID is not a string;
  • fix error getting annots/fields if there are none;
  • fix startTool to start a tool on app.doc;
  • fix changing color of fields inside elements
Changes in v1.4 (not posted):
  • code changes: move DialogDataStore class property declarations to constructor, and make DialogDescription a constructor function;
  • fix typo on startTool setup;
  • fail gracefully if no ClrUtx;
  • compress with minify-js.com (ecma 2016)


Usage Example 5:
The above Example 1 has a color picker for the text and outline. This example expands on it by adding another color picker to pick a different color for the background.

I want the background to be semi-transparent, so first I duplicate the outline (copy and then paste into the same position). With this second copy, I set the background color to white, border thickness to zero, and opacity to 20%:
image.png
Then I set the author to "%color1 FS%". I already used "color" for the previous color dialog, so now I'm using "color1". And remember that F is for the fill color, S is for the stroke color.
image(1).png
Now I put this annotation into the background (Ctrl-] on my computer or with the right click menu Arrange > Send to Back)
image(2).png
The additional color picker takes one more colorConstructor: { color1: color.transparent, description: "Background:"}

Code: Select all

xutil.stampDialog( "#mBl0HFq5t6Y_02DVbBhbM1", 
	{ field: "hexagon", description: "Enter value:", value: "A", increment: function(){
	let fv = this.globals[this.field] ?? this.value; // current field value
	let t = isNaN(fv) ? (fv === fv.toUpperCase() ? 'C' : 'c') : ''; // try to guess whether letters or numbers
	return [1, t]}},
	{ color: color.red, description: "Color:", strokeColor: true },
	{ color1: color.transparent, description: "Background:"});
The resulting dialog has an additional color picker to pick the background color:
image(3).png
and the resulting stamp:
image(4).png
You do not have the required permissions to view the files attached to this post.
Last edited by Mathew on Sat Aug 02, 2025 12:10 am, edited 10 times in total.
User avatar
Daniel - PDF-XChange
Site Admin
Posts: 11733
Joined: Wed Jan 03, 2018 6:52 pm

Re: [javascript] easier dynamic stamp creation

Post by Daniel - PDF-XChange »

Hello, Mathew

I feel like every time I check one of these threads I am humbled by the power of your scripts.
Thank you once again for sharing functions like this with the rest of us!

Kind regards,
Dan McIntyre - Support Technician
PDF-XChange Co. LTD

+++++++++++++++++++++++++++++++++++
Our Web site domain and email address has changed as of 26/10/2023.
https://www.pdf-xchange.com
Support@pdf-xchange.com
Mathew
User
Posts: 668
Joined: Thu Jun 19, 2014 7:30 pm

Re: [javascript] easier dynamic stamp creation

Post by Mathew »

Usage Example 6
This example is a bit contrived, to show what the ok() parameter could be used for, and how to change other properties of annotations in the stamp before they are all flattened and the stamp is placed.

The above Example 5 added a background color option. That's fine, except I have three cases I usually want:
  1. Background transparent (ie no fill);
  2. Background white (so that it masks anything behind); or
  3. Background the same color as I picked for the outline
Note that if just setting background color based on the results of a popup (drop down menu), Example 4 would be easier; but I also want to change the transparency of the background, so that when it's white it's almost opaque, but when color it has low opacity and there's some contrast with the text in front of it. To do this we need to get back into javascript, something I was -- ironically -- trying to avoid by creating this library in the first place. :shock:

Starting with the stamp in Example 5, I add a field that does not exist on the stamp, just gets the result of a popup (dropdown), and an ok() function to handle changing colors based on the value in the field. Here's the dialogConstructor:

Code: Select all

xutil.stampDialog( "#mBl0HFq5t6Y_02DVbBhbM1", 
	{ field: "hexagon", description: "Enter value:", value: "A", increment: function(){
	let fv = this.globals[this.field] ?? this.value; // current field value
	let t = isNaN(fv) ? (fv === fv.toUpperCase() ? 'C' : 'c') : ''; // try to guess whether letters or numbers
	return [1, t]}},
	{ color: color.red, description: "Color:", strokeColor: true },
{ field: 'bgFill', description: "Background:", type: 'popup', value:['Transparent','White','Color'], ok(stamp) {
    let nPage = stamp.getField(event.targetName).page;
    let anns = stamp.getAnnots(nPage).filter( a => /%color1.+?F.*%/.test(a.author + a.subject));
    switch (this.globals['bgFill']) {
      case 'Transparent':
        anns.forEach( a => a.opacity = 0);
        break;
      case 'White':
        anns.forEach( a => {
          a.opacity = 0.8;
          a.fillColor = color.white;
        });
        break;
      default: // color
        anns.forEach( a => {
          a.opacity = 0.15;
          a.fillColor = this.globals.color;
        });
    }
}});
This now gives the following dialog, with a popup with the three options 'Transparent','White','Color':
image.png
and the color and transparency are handled within the script.

Detailed Explanation:
Starting at line 7 in the constructor, I've added a field: 'bgFill' as a placeholder for the value that gets returned from the popup. I added a description, and the type 'popup' is a dropdown menu. The values are given as an array ['Transparent','White','Color'] so that text will be both the text that's shown, and the result that gets returned. Next is the more complicated part.

The 'ok' parameter runs a function after "OK" is pressed on the dialog. At this point, all the values from the dialog are known, and have been entered into a globals property of the dialogConstructor.

The first line of this script gets the page in the stamp by getting the field that caused this event (in this case 'hexagon') and getting its page property. The next line gets all annotations on that page, and filters them based on whether their author or subject match the regular expression /%color1.+?F.*%/ (ie the color1 tag and F for fill).

Next, the script uses this.globals['bgFill'] to get the results of the popup from the dialog.
  1. If it's 'Transparent' I just set the opacity to 0.
  2. If it's 'White' I set the opacity to 0.8 (80%) so it almost completely obscures everything below, and set the fillColor to color.white.
  3. If it's default (ie none of the above) I'm assuming its "Color" and I set the opacity to 15% and get the color from this.globals.color (the color picked for the text and outline).
image(1).png
More stamps!
I've attached the stamp file from Example 1, but changed to have the above dialog modifications.
Shapes.pdf
You do not have the required permissions to view the files attached to this post.
Last edited by Mathew on Sat Apr 12, 2025 2:20 pm, edited 2 times in total.
Mathew
User
Posts: 668
Joined: Thu Jun 19, 2014 7:30 pm

Re: [javascript] easier dynamic stamp creation

Post by Mathew »

Usage Example 7
This example shows how you can style the dialog box to lay out the input boxes how you want, and how to start another tool as soon as the stamp is placed. I'm making a weld symbol stamp that has inputs for the weld size. All the linework is drawn as annotations (not flattened) so I can also change the color.
image(3).png
For the annotations, I set the author to %color S%
image.png
For the form fields I set the tooltip to %color T%
image(1).png

Code: Select all

xutil.stampDialog("52c85d2b-4573-4189-bab565f977d20e9b",
{description: "Fillet Near Side", type: 'cluster', align_children: 'align_row', elements:[
	{field: 'fwNS_size', description: "Size", width: 100, labelWidth:30},
	{field: 'fwNS_length', description: "Length-spacing", width: 170, labelWidth: 90} ]},
{color: color.red, description: "Color:", strokeColor:true},
{startTool: 'cmd.tool.annot.arrow'})
Detailed Explanation:
The first dialogConstructor has a description, but no field, and is type: 'cluster'. There are two types that can contain other elements 'cluster' which has a title text area and draws a box around everything that it contains; and 'view' which is an invisible container. I want to put two dialog fields on the same line, so I've set align_children: 'align_row'. The elements property is an array that is a list of all the dialogConstructors that will be inside this 'cluster'.

I have two fields inside the cluster, and have set width and labelWidth on them to reduce the size of the input box and get things to fit nicely on one line.

The elements property must start and end with square brackets (it's a javascript array) [dialogConstructor1, dialogConstructor2... ].

I've added a color picker, and it will set the strokeColor of the stamp to match the color that the stamp elements are.

startTool is set to 'cmd.tool.annot.arrow' so that as soon as the stamp is placed, the arrow tool is activated and I can draw an arrow to the weld location.

This is the resulting dialog:
image(2).png
As soon as the stamp is placed, the arrow tool is activated:
image(4).png
For a double sided weld, I just duplicate the cluster for the top and bottom:

Code: Select all

xutil.stampDialog("593178fa-8456-4990-9421af962a45125d",
{description: "Fillet Far Side", type: 'cluster', align_children: 'align_row', elements:[
	{field: 'fwBFS_size', description: "Size", width: 100, labelWidth:30},
	{field: 'fwBFS_length', description: "Length-spacing", width: 170, labelWidth: 90} ]},
{description: "Fillet Near Side", type: 'cluster', align_children: 'align_row', elements:[
	{field: 'fwBNS_size', description: "Size", width: 100, labelWidth:30},
	{field: 'fwBNS_length', description: "Length-spacing", width: 170, labelWidth: 90} ]},
{color: color.red, description: "Color:", strokeColor:true},
{startTool: 'cmd.tool.annot.arrow'})
gives this dialog:
image(6).png

Here's the stamp file with all the weld symbols:
weldSymbols.pdf
image(5).png
You do not have the required permissions to view the files attached to this post.
Last edited by Mathew on Mon Apr 14, 2025 2:48 pm, edited 1 time in total.
User avatar
Stefan - PDF-XChange
Site Admin
Posts: 19917
Joined: Mon Jan 12, 2009 8:07 am

Re: [javascript] easier dynamic stamp creation

Post by Stefan - PDF-XChange »

Hello Mathew,

Many thanks for the stamps collection and detailed usage instructions! Much appreciated!

Kind regards,
Stefan
Mathew
User
Posts: 668
Joined: Thu Jun 19, 2014 7:30 pm

Re: [javascript] easier dynamic stamp creation

Post by Mathew »

This update incorporates the updated ClrUtx color picker with the stamp utils, so that instead of selecting a color by name
image(2).png
the stamp dialog will have the actual color shown and use the ClrUtx color picker:
image.png
xutil.stampUtils v1.6.zip
Changes in v1.6
  • update to v2.1 of ClrUtx color picker (instead of dropdown with color names)
You do not have the required permissions to view the files attached to this post.
User avatar
Dimitar - PDF-XChange
Site Admin
Posts: 2455
Joined: Mon Jan 15, 2018 9:01 am

Re: [javascript] easier dynamic stamp creation

Post by Dimitar - PDF-XChange »

Thanks Mathew.
Mathew
User
Posts: 668
Joined: Thu Jun 19, 2014 7:30 pm

Re: [javascript] easier dynamic stamp creation

Post by Mathew »

Example 8

All the above examples show the more advanced options for this tool. This example is a full step-by-step to show how one would set up a stamp so that the color of the stamp can be changed when it is placed. [edit] As of version 10.6 as Daniel points out below, it is much easier to edit stamps. Unfortunately it still flattens markup, so it prevents the stamp from changing colors, so I still need to use the old method.

The example stamp is one of the built-in "Standard" stamps.

  1. The first step is to create the stamp using annotation (markups). I made a polygon with curved corners, and a text box, rotated them 1 degree. To make the shadow, I duplicated everything, made it light grey, moved it slightly to the right and down, and put it in the background:
    image(1).png
  2. Now I select all these markups and make a new stamp from it. Stamps Palette > New Stamp from Selection…
    image(3).png
    I'm making a new collection "Standard Colors" for these stamps:
    image(4).png
    Tip: If I am making multiple stamps, I find it quicker to do the above for all the stamps, then do the following steps for all of them at the same time.
  3. I need the stamp ID for the new stamp, so I open a blank document, place the stamp, and read the stamp id from the properties toolbar:
    image(5).png
    If working on multiple stamps at the same time, one can place and select them all and run the following script to get all the stamp ID's output to the console:

    Code: Select all

    for (let a of this.selectedAnnots) console.println('\n' + a.subject + "\n" + a.AP);
  4. I make sure to save my document with the markups that I made the stamps from. I'll need that again. Then Quit PDF XChange.
  5. Move the newly created stamp file to the Desktop from %APPDATA%\Tracker Software\PDFXEditor\3.0\Stamps and then open it.
  6. The program will have flattened all the markups in the newly created stamp. So I select everything with the "Edit Objects" tool, and delete them. Then go back to the file with the original annotations, and copy paste them here.
  7. To make the stamp work as a dynamic stamp, it needs at least one form field. I don't want it to show up in the stamp, so made it a hidden field:
    image(2).png
    (Unnecessary, but I also put this field in the background with right click > Arrange > Send to Back)
  8. Add a calculation script to this field by selecting it and in the Properties pane under Value Calculation > Custom Action then scroll down and click on the ellipsis after Run a JavaScript. Add the following script:

    Code: Select all

    xutil.stampDialog( "#XCEP95Nsx7cy#Fvw86r030", 
    	{ color: color.blue, description: "Color:", strokeColor: true });

    On the first line, I've pasted the stamp ID that I got earlier, inside quote marks.
    The second line sets up the color picker dialog. color.blue is the default color that it will offer the first time the stamp is placed. After that, it will remember the last color picked. The text after description is the prompt that will be displayed. strokeColor: true sets the stroke color of the placed stamp to match the color that was picked. The stroke color of stamps is not actually displayed, but shows up when listing markups (annotations).
  9. Penultimate step: For the tool to know which markups to change color, I need to add %color % flags to the Author property of markups. First I select all line annotations I want to change stroke colors and, in Properties, I add the following to the Author %color S% (S is to set the stroke color)
    image(6).png
    Then select the text markup and add to the Author %color T% (T is to set the text color)
  10. Now save, quit PDF XChange, and move the stamp file back from the Desktop to the Stamps folder.
Now when I pick this stamp, it will show a dialog for me to pick what color I want to make it:
image(8).png
image(9).png
Stamps!
Here is the stamp file I was working on in this example, with a few more of the Standard stamps added.

The "Experimental" stamp allows you to enter your own text.
image.png
Standard Color.pdf
You do not have the required permissions to view the files attached to this post.
Last edited by Mathew on Wed Aug 20, 2025 12:35 am, edited 12 times in total.
User avatar
Daniel - PDF-XChange
Site Admin
Posts: 11733
Joined: Wed Jan 03, 2018 6:52 pm

Re: [javascript] easier dynamic stamp creation

Post by Daniel - PDF-XChange »

Hello, Mathew

It may be a bit late to say this, but... guess what we've got as a new feature?

https://www.pdf-xchange.com/knowledgeba ... ting-stamp

This means it is no longer necessary to do the steps of locating and removing the stamps from the Stamps folder, and in most cases, it is not necessary to restart the Editor during the process either. You can make a stamps, open the stamp palette, "right click > edit" make your changes, including adding JS and dynamic content, and then save and close the file. The stamp should be immediately usable.

Kind regards,
Dan McIntyre - Support Technician
PDF-XChange Co. LTD

+++++++++++++++++++++++++++++++++++
Our Web site domain and email address has changed as of 26/10/2023.
https://www.pdf-xchange.com
Support@pdf-xchange.com
Mathew
User
Posts: 668
Joined: Thu Jun 19, 2014 7:30 pm

Re: [javascript] easier dynamic stamp creation

Post by Mathew »

Daniel - PDF-XChange wrote: Tue Aug 19, 2025 7:12 pm Hello, Mathew

It may be a bit late to say this, but... guess what we've got as a new feature?

https://www.pdf-xchange.com/knowledgeba ... ting-stamp

This means it is no longer necessary to do the steps of locating and removing the stamps from the Stamps folder, and in most cases, it is not necessary to restart the Editor during the process either. You can make a stamps, open the stamp palette, "right click > edit" make your changes, including adding JS and dynamic content, and then save and close the file. The stamp should be immediately usable.

Kind regards,
Hah! Fantastic. :shock:

However: For the purpose of this I can't use it, because saving the stamp through that process flattens the markups. Is there a way to find the stamp id from within that stamp editor?
Last edited by Mathew on Tue Aug 19, 2025 9:12 pm, edited 1 time in total.
Mathew
User
Posts: 668
Joined: Thu Jun 19, 2014 7:30 pm

Re: [javascript] easier dynamic stamp creation

Post by Mathew »

I've posted an update v1.7 above to fix a bug I ran into making the example 8. Also updated in the first post.
xutil.stampUtils v1.7.zip
Changes in v1.7
  • include fields with no description when setting color
  • clearly cite license
  • 'this' refers to the current constructor for methods on the 'value' parameter
Source
xutil.stampUtils.source v1.7.zip
You do not have the required permissions to view the files attached to this post.
Last edited by Mathew on Tue Aug 19, 2025 11:17 pm, edited 1 time in total.
User avatar
Daniel - PDF-XChange
Site Admin
Posts: 11733
Joined: Wed Jan 03, 2018 6:52 pm

Re: [javascript] easier dynamic stamp creation

Post by Daniel - PDF-XChange »

Hello, Mathew

Hmm, I cant say much about the flattening of markups, though I am surprised that is happening. I thought that stamps could contain them and only need to be flattened during placement. I will ask around about this.
Mathew wrote: Tue Aug 19, 2025 7:31 pm Is there a way to find the stamp id from within that stamp editor?
The same way you would normally, via the properties pane, just place a copy of the stamp anywhere (it is still usable while you are editing it), you can quickly copy the ID from there, and then remove the placed stamp item.

Kind regards,
Dan McIntyre - Support Technician
PDF-XChange Co. LTD

+++++++++++++++++++++++++++++++++++
Our Web site domain and email address has changed as of 26/10/2023.
https://www.pdf-xchange.com
Support@pdf-xchange.com
Mathew
User
Posts: 668
Joined: Thu Jun 19, 2014 7:30 pm

Re: [javascript] easier dynamic stamp creation

Post by Mathew »

Daniel - PDF-XChange wrote: Tue Aug 19, 2025 11:06 pm Hmm, I cant say much about the flattening of markups, though I am surprised that is happening. I thought that stamps could contain them and only need to be flattened during placement. I will ask around about this.
Here's how to reproduce:
  1. Use some annotations to make a stamp
  2. Use Edit from the stamps palette
  3. Any markups used to initially make the stamp will have been flattened (we knew this)
  4. Delete the flattened markup with the edit objects tool
  5. Paste in annotations (or make new ones) while editing the stamp.
  6. Save and close the editing tab.
  7. Go back to the stamps palette and edit it again.
  8. All the markups will have been flattened
It behaves like it's using the same process to save as it did when initially making the stamp, and because that flattens annotations, it also does when editing.
User avatar
Daniel - PDF-XChange
Site Admin
Posts: 11733
Joined: Wed Jan 03, 2018 6:52 pm

Re: [javascript] easier dynamic stamp creation

Post by Daniel - PDF-XChange »

Hello, Mathew

8) RT#7610: FR: Stop stamp edit tool from flattening comments on save

Kind regards,
Dan McIntyre - Support Technician
PDF-XChange Co. LTD

+++++++++++++++++++++++++++++++++++
Our Web site domain and email address has changed as of 26/10/2023.
https://www.pdf-xchange.com
Support@pdf-xchange.com
unix2000
User
Posts: 4
Joined: Thu Nov 30, 2023 1:29 am

Re: [javascript] easier dynamic stamp creation

Post by unix2000 »

Mathew wrote: Wed Apr 02, 2025 7:50 pm This tool (library) makes it much easier to add dynamic fields with a dialog to stamps. It also adds functionality to change the color of the stamp elements in the dialog, set the strokeColor or other properties of the stamp after it's placed, and start another menu item immediately after the stamp is placed. It will also save the values entered into fields for the next time you use the stamp.

The color changing functionality takes advantage of the trick that if there are annotation (markup) objects in a stamp, they can be manipulated by a script immediately before the stamp is placed. When the stamp is placed, all these objects get flattened into the stamp by PDF XChange. I've only tested in PDF XChange 10.5.2.


One still needs to go through the usual rigmarole to get the stamp ID, but all of the code for generating the dialog, and filling in form fields, is handled.

Installation
Unzip and save in JavaScripts folder, then restart PDF XChange. You may need to make the folder. Either in
C:\Users\[USERNAME]\AppData\Roaming\Tracker Software\PDFXEditor\3.0\Javascripts
OR so that all users have access:
C:\Program Files\Tracker Software\PDF Editor\Javascripts
xutil.stampUtils v1.7.zip


Examples
I've posted some usage examples below in separate posts, included sample stamp sets that make use of this library.
Example 1: Dialog with one field, color picker and auto-increment
Example 2: Multiple form fields, and auto-calculated date field
Example 3: Stamp Properties: Setting stamp subject based on form field value
Example 4: Using form fields and functions to set other properties and stamp colors
Example 5: Adding additional colors to stamps
Example 6: Running scripts before the stamp is placed, and changing properties of annotations in the stamp
Example 7: Weld symbol stamps that start the arrow tool
Example 8: Set color of stamp elements. This example shows all the steps for creating a dynamic stamp.

Usage
Assign a custom action to one of the form fields. For the custom action, call this function.

Code: Select all

xutil.stampDialog( stampID, dialogConstructor[, dialogConstructor, ...])
stampID this is the ID for this stamp
dialogConstructor is an object that has various key:value pairs for each dialog field you want to create. The keys and their acceptable values are as follows:
field: "FieldName" (optional) the form field in the stamp that will be filled from the dialog.
  • FieldName is also the globals key under which the entered value is stored for the next time the stamp is used. If you skip the field parameter, it will create static text from description unless it's a 'button' in which case this parameter is ignored.
  • description: "Field description text" (optional only if there's a field paramenter) If null or omitted it skips the dialog and assigns the default value - use an empty string "" if no description needed.
  • value: "Default value" or function(), (optional assigns "" if omitted)
    For radio, list box or combo box, the format is [item1, item2, ...] The items can either be a string, in which case that is what is both displayed and returned, or an object {value:"code", description:"Text description"} in which case the description is displayed, but the value is returned.
  • type: (optional) type of dialog box item - if omitted gets type from field (check_box, radio, list_box, hier_list_box, static_text, edit_text, popup, button, cluster, view)
  • handler( dialog ): (optional) function to call when the dialog item is clicked or changed.
    Required for type: 'button', where the field parameter is ignored.
    'this' is the dialog monitor and 'dialog' is the dialog object.
    • Note that the dialog monitor is supplied with two properties to help decipher which field maps to which dialog element:
      this.fields is a list of all fields, and their index is the index on the item_id for dialog elements 'db00' is the first, 'db01' second, etc
      this.radios is a list of radio buttons with the value [field, returnValue]; the item_id for radios is 'rd00', 'rd01', etc based on the index in the this.radios; and the group_id is the field item_id from this.fields
  • increment: value (optional) 'value' is either:
    • a number to increment by (ie 1, -2, etc). Increment happens before the dialog is shown; or
    • an array [incVal, format] where 'incVal' is the number to increment by (or zero), and 'format' is one of the following: r,R,c,C,nWidth (roman lowercase, roman uppercase, alphabet lowercase, alphabet uppercase, number of digits)
  • labelWidth: (optional) sets the width of the auto-generated label on edit_text, popup, list_box
  • ok( stamp ): (optional) function to run after the ok button is pressed.
    'stamp' is the current stamp, and 'this' is the current dialogConstructor,
  • globals: for each of the dialogObjects, this is the saved global variables for this stamp, in the form {key:value, ...} where key is the fieldName. It has access to any saved field values for the whole stamp file. It is updated with the information from the dialog box before ok() is run. Note: If using globals to get the values of other fields, field values are updated in globals in the order they are processed, so data for dialogConstructors below the current one will be old (from the previous time the stamp was used)
  • setProp: (optional) stamp property name to set from the value of this field, or {property:value} object to supply the value.
  • (optional) other parameters can be passed to dialog such as 'width', 'height', 'char_width', 'char_height', 'font', 'bold', 'italic', 'alignment', 'multiline', 'multi_select', 'separator:1', 'align_children',etc
The following properties should have their own dialogConstructor objects:
colorX: defaultColor or function()
  • description: "Color Dialog Description", (optional) sets a color picker dialog - if null or omitted then no dialog and it assigns the default color
  • strokeColor: true (optional) to set the strokecolor of the stamp
    To get the color on objects to change, they need to be annotations or fields. Annotation subject or author, and Field Tooltip or Mapping Name must contain the text %colorX TFS% where X is an optional index if there are multiple color pickers and T,F,S is for text, fillcolor or strokeColor is set
    For example: %color S% to set the text and stroke color if there's only one color dialog item
    The globals property will be updated with all current field values before the colors are applied
startTool: "cMenuItem" - runs app.execMenuItem("cMenuItem") after the stamp is placed. If you pass it a function, it will run that function.


The above example will throw a javascript exception if someone with the stamp file is missing xutil.stampUtils.js (ie they only got a copy of the stamp file). I'm not sure why this would happen :wink: , but if you want it to fail gracefully and just act like a static stamp, revise the function call thus:

Code: Select all

    // alternative that checks first if xutil.stampDialog method exists:
    if ("object" === typeof xutil) xutil.stampDialog?.( stampID, dialogConstructor, ... );

Debugging
With the stamp file open, you can run the javascript code in the console to check how it works before pasting it into the custom action for the field. It should open a dialog and fill fields/change colors as it would when the stamp is placed. It will also output any errors it encounters into the console.


Limitations
  • Once a stamp is started, I don't think there's anything a script can do to stop it. I used to have a Cancel button on stamp dialogs, but it couldn't cancel the stamp placement. I started using the cancel button as a "reset" (ie I'd clear all the fields), but it's such a rare occurrence that I need to clear the fields (I can go through and clear them myself before placing the stamp if I absolutely want a blank stamp). So I only show an OK button now.
  • Dynamic stamps relying on this tool must be used on applications able to run this tool! It is not tested on software other than PDF XChange Editor. I didn't use any PXCE special javascript, so it may work on other applications, although they tend to not be as up to date on javascript. Let me know. If it's just a matter of minor tweaks, I'll try to do them. But I'm not willing to re-write it in an earlier version of javascript, for example.

Source Code
The tool is released under the MIT (Expat) license. I post the source code here: viewtopic.php?t=44731

Hi I followed this topic, and downloaded the weld stamps and saved on my "Stamps" folder --> C:\Users\MYFRIENDUSERNAME\AppData\Roaming\Tracker Software\PDFXEditor\3.0\Stamps

, also the required .JS files which is saved in "JavaScripts" folder --> C:\Users\MYFRIENDUSERNAME\AppData\Roaming\Tracker Software\PDFXEditor\3.0\JavaScripts,

Its working on my local pc, but it does not work on my friends computer. I'm getting a "not define" error. I will appreciate your guidance. thanks again.

Please see photo for reference.
image.png
You do not have the required permissions to view the files attached to this post.
User avatar
Daniel - PDF-XChange
Site Admin
Posts: 11733
Joined: Wed Jan 03, 2018 6:52 pm

Re: [javascript] easier dynamic stamp creation

Post by Daniel - PDF-XChange »

Hello, unix2000

There have been a number of changes to JS in recent builds, allowing for new functionality, and fixing some old "functions" which were actually bugs. Most of Mathew's scripts have been updated to the new (correct) implementation, and so your friend will need to update the software, to the current version, to be able to fully utilize the scripts he has created.

Kind regards,
Dan McIntyre - Support Technician
PDF-XChange Co. LTD

+++++++++++++++++++++++++++++++++++
Our Web site domain and email address has changed as of 26/10/2023.
https://www.pdf-xchange.com
Support@pdf-xchange.com
Mathew
User
Posts: 668
Joined: Thu Jun 19, 2014 7:30 pm

Re: [javascript] easier dynamic stamp creation

Post by Mathew »

unix2000 wrote: Wed Sep 17, 2025 10:23 pm
Its working on my local pc, but it does not work on my friends computer. I'm getting a "not define" error. I will appreciate your guidance. thanks again.

Please see photo for reference.

image.png
Hi unix2000,

I think in this case it's just that colorUtils depends on 1ang.js and I forgot to include 1ang.js in the zip file. Download it here: viewtopic.php?p=182242#p182242

I'll update the zip file above to include it, until I fix the dependency in colorUtils.

Thanks for letting me know!
Mathew.
unix2000
User
Posts: 4
Joined: Thu Nov 30, 2023 1:29 am

Re: [javascript] easier dynamic stamp creation

Post by unix2000 »

Daniel - PDF-XChange wrote: Wed Sep 17, 2025 10:27 pm Hello, unix2000

There have been a number of changes to JS in recent builds, allowing for new functionality, and fixing some old "functions" which were actually bugs. Most of Mathew's scripts have been updated to the new (correct) implementation, and so your friend will need to update the software, to the current version, to be able to fully utilize the scripts he has created.

Kind regards,
Thanks a lot! it did worked! ...
unix2000
User
Posts: 4
Joined: Thu Nov 30, 2023 1:29 am

Re: [javascript] easier dynamic stamp creation

Post by unix2000 »

Mathew wrote: Wed Sep 17, 2025 11:38 pm
unix2000 wrote: Wed Sep 17, 2025 10:23 pm
Its working on my local pc, but it does not work on my friends computer. I'm getting a "not define" error. I will appreciate your guidance. thanks again.

Please see photo for reference.

image.png
Hi unix2000,

I think in this case it's just that colorUtils depends on 1ang.js and I forgot to include 1ang.js in the zip file. Download it here: viewtopic.php?p=182242#p182242

I'll update the zip file above to include it, until I fix the dependency in colorUtils.

Thanks for letting me know!
Mathew.

I downloaded the file as suggested and it did worked!, I really appreciate your time to response.
User avatar
Dimitar - PDF-XChange
Site Admin
Posts: 2455
Joined: Mon Jan 15, 2018 9:01 am

[javascript] easier dynamic stamp creation

Post by Dimitar - PDF-XChange »

:)