Copy link to clipboard
Copied
I've been fighting an issue with creating a dynamic stamp. I can't seem to get popup menus (list boxes) in dialog boxes working. The popup menu is displayed properly in the dialog box, but there is no content in the dropdown, although it is defined.
The javascript is in two locations.
The global (document) javascript:
var builder =
{
// These map to Text Fields in the Stamp
textBoxes :
[
{ field:"Name", description:"Name:", default:function() { return ""; } },
{ field:"Company Name", description:"Company Name:", default:function() { return ""; } },
],
// This maps to a Popup Group in the PDF named 'Project'
popupGroup: "Plan Section",
listItems :
[
{popupItems :
{
//list of items of Popup menu, positive number indicates default selection
"Road": -1,
"Bridge": -1,
"Traffic": -1,
"ITS": -1
}
}
],
// This maps to a Radio Group in the PDF named 'Status'
radioGroup : "Type of Plans",
radioButtons :
[
// value maps to the 'Choice' of each radio button in the group, description will show on the dialog
{ value:"", description:"Original Plans" },
{ value:"Revised Plans", description:"Revised Plans" },
{ value:"As-Built Plans", description:"As-Built Plans" }
],
radioErrorMsg : "Please select a status"
}
And here's the javascript contained in a hidden calculations field on the stamp:
if (event.source.forReal)
{
var stampDialog = CreateDialog(builder);
app.execDialog(stampDialog);
this.getField(builder.radioGroup).value = stampDialog.radioSelection;
this.getField(builder.popupGroup).value = stampDialog.popupSelection;
for (var i = 0; i < builder.textBoxes.length; ++i)
{
var t = builder.textBoxes;
this.getField(t.field).value = stampDialog.textBoxResults;
}
}
function CreateDialog(dialogBuilder)
{
var sd = new Object();
sd.builder = dialogBuilder;
sd.radioSelection = "";
sd.popupSelection = "";
sd.textBoxResults = new Array();
var popupElements = new Array();
popupElements[0] =
{
type: "popup",
item_id: "popupItems",
field: sd.builder.popupGroup,
width: 250
};
var popupCluster =
{
type: "cluster",
name: builder.popupGroup,
elements: popupElements
};
var stateElements = new Array();
for (var i = 0; i < dialogBuilder.radioButtons.length; ++i)
{
var c = dialogBuilder.radioButtons;
stateElements =
{
type: "radio",
name: c.description,
item_id: "rad" + i,
group_id: "grp1"
};
}
var stateCluster =
{
type: "cluster",
name: "Status",
alignment: "align_center",
align_children: "align_distribute",
elements: stateElements
};
var optionsElements = new Array();
for (var i = 0; i < dialogBuilder.textBoxes.length; ++i)
{
var view = new Object();
view.type = "view";
view.align_children = "align_row";
view.elements = new Array();
var t = dialogBuilder.textBoxes;
var s = new Object();
s.type = "static_text";
s.item_id = "sta" + i;
s.name = t.description;
s.width = 90;
var e = new Object();
e.type = "edit_text";
e.item_id = "edt" + i;
e.width = 150;
view.elements[0] = s;
view.elements[1] = e;
optionsElements = view;
}
var optionsCluster =
{
type: "cluster",
name: "Options",
elements: optionsElements
};
sd.initialize = function(dialog)
{
var init = new Object();
for (var i = 0; i < this.builder.textBoxes.length; ++i)
{
var t = this.builder.textBoxes;
var id = "edt" + i;
init[id] = t.default();
}
dialog.load(init);
dialog.load(this.builder.listItems[0]);
};
sd.commit = function(dialog)
{
var res = dialog.store();
for (var i = 0; i < this.builder.radioButtons.length; ++i)
{
var c = this.builder.radioButtons;
var id = "rad" + i;
if (res[id] == true)
{
this.radioSelection = c.value;
break;
}
}
for (var i = 0; i < this.builder.textBoxes.length; ++i)
{
var t = this.builder.textBoxes;
var id = "edt" + i;
this.textBoxResults = res[id];
}
for (var i in res["popupItems"])
if (res["popupItems"] >0)
{
this.popupSelection = i;
}
};
sd.validate = function(dialog)
{
var res = dialog.store();
for (var i = 0; i < this.builder.radioButtons.length; ++i)
{
var c = this.builder.radioButtons;
var id = "rad" + i;
if (res[id] == true)
return true;
}
app.alert(this.builder.radioErrorMsg);
return false;
};
sd.description =
{
name: "Stamp Dialog",
elements:
[
{
type: "view",
align_children: "align_fill",
elements:
[
popupCluster,
stateCluster,
optionsCluster
]
},
{
type: "ok"
}
]
};
return sd;
}
All item_id values must be unique 4 character strings. It appears you're using "popupItems", and there's the potential for others not to be 4 characters either (e.g., "edt" + i, where i >= 10).
Copy link to clipboard
Copied
All item_id values must be unique 4 character strings. It appears you're using "popupItems", and there's the potential for others not to be 4 characters either (e.g., "edt" + i, where i >= 10).
Copy link to clipboard
Copied
Thanks George.
That was it... I changed "popupitems" to "popl" and that solved the problem.
Copy link to clipboard
Copied
For an easy way to create Acrobat JavaScript Dialogs, see this: ACRODIALOGS OVERVIEW
It enforces the 4 characters limit on item_id values.
Copy link to clipboard
Copied
Thanks Thom, so I went and created this UI. The application requires that the date is cut and paste into the dialog (among other things) but the dialog steals focus and will not let the user cut and paste from the pdf. Is there some way that the dialog can operate without stealing focus from the document?
////////////////////////////////////////////////////////////////
// Acrobat JavaScript Dialog
//
list_Lst3 = {};
list_Lst4 = {};
var oJSDlg = {
ccDate:"00/00/0000",
sectionCoords:"0,0 - 0,0",
bChk2:null,
strLst3:null,
strLst4:null,
strEdt8:null,
summaryData:null,
GetListSel:function(oLst){for(var x in oLst){if(oLst
initialize:function(dialog){
var oInit = {
Edt1:this.ccDate,
Edt5:this.sectionCoords,
Chk2:this.bChk2,
Lst3:this.strLst3,
Lst4:this.strLst4,
Edt8:this.strEdt8,
Edt7:this.summaryData,
Lst3:list_Lst3,
Lst4:list_Lst4
};
dialog.load(oInit);
},
validate:function(dialog){
var bRtn = true;
var oRslt = dialog.store();
return bRtn;
},
commit:function(dialog){
var oRslt = dialog.store();
this.ccDate = oRslt.Edt1;
this.sectionCoords = oRslt.Edt5;
this.bChk2 = oRslt.Chk2;
this.strLst3 = this.GetListSel(oRslt.Lst3);
this.strLst4 = this.GetListSel(oRslt.Lst4);
this.strEdt8 = oRslt.Edt8;
this.summaryData = oRslt.Edt7;
},
description:{
name:"TEST BUILDER",
elements:[{type:"view",elements:[
{
type:"cluster",
item_id:"Cls2",
name:"Event Date",
elements:[
{
type:"edit_text",
item_id:"Edt1",
width:101,
height:20,
},
{
type:"button",
item_id:"But2",
name:"Normalize Date",
},
{
type:"edit_text",
item_id:"Edt5",
width:105,
height:20,
},
{
type:"button",
item_id:"But3",
name:"Normalize Area Coordinates",
},
],
},
{
type:"cluster",
item_id:"Cls7",
name:"Segment Builder",
elements:[
{
type:"check_box",
item_id:"Chk2",
name:"Verify Record",
},
{
type:"static_text",
item_id:"Sta4",
name:"Service Type (Select ONE Service Type)",
},
{
type:"list_box",
item_id:"Lst3",
width:307,
height:50,
},
{
type:"static_text",
item_id:"Sta5",
name:"Tag Highlighter (List of Tags found and highlighted on this Page)",
},
{
type:"list_box",
item_id:"Lst4",
width:309,
height:70,
},
{
type:"button",
item_id:"But1",
name:"Tag Editor",
alignment:"align_center",
},
{
type:"static_text",
item_id:"Sta6",
name:"Snippet Builder",
},
{
type:"edit_text",
item_id:"Edt8",
width:315,
height:115,
multiline:true,
},
],
},
{
type:"cluster",
item_id:"Cls6",
name:"Composer",
elements:[
{
type:"edit_text",
item_id:"Edt7",
width:312,
height:132,
multiline:true,
},
],
},
{
type:"ok_cancel_other",
ok_name:"<<Previous",
cancel_name:"Next >>",
other_name:"Save & Exit",
},
]}]
}
}
if("ok"==app.execDialog(oJSDlg))
{
console.println("ccDate = "+oJSDlg.ccDate);
console.println("sectionCoords = "+oJSDlg.sectionCoords);
console.println("bChk2 = "+oJSDlg.bChk2);
console.println("strLst3 = "+oJSDlg.strLst3);
console.println("strLst4 = "+oJSDlg.strLst4);
console.println("strEdt8 = "+oJSDlg.strEdt8);
console.println("summaryData = "+oJSDlg.summaryData);
}
Copy link to clipboard
Copied
That is just how dialogs work, they keep the focus. However, it may be possible for the date to be automatically copied from the PDF. Does this date appear in the same location? is it in a form field?
Copy link to clipboard
Copied
They are all over the place Thom and to make it more complicated there are many types of dates. We can parse and recover the entire list of dates and offer the user a drop down choice but that can be confusing for the user. We are thinking of having a form on another page or another pdf. Forms don’t seem to steal focus the same way.
Copy link to clipboard
Copied
They do not. There is another solution. The dialog can be setup so that the user can dismiss it, then return to fill out the date. It's just a matter of saving the other data on the dialog so it automatically repopulates.
Copy link to clipboard
Copied
The app we have functional does exactly that. We name a destination at user defined coordinates, set a selectable annotation and exchange data with a JSON attachment on user request. The component functions well but the UI is clunky due to the back and forth. User needs to process thousands of pages so we will try the form approach. Our plan if that does not work well is to develop this component in Java and use JavaScript only as necessary. Thanks for confirming this focus issue, I thought we were missing something. Your site pdfscripting.com has been very helpful.
Copy link to clipboard
Copied
Another option is to create an Acrobat Plug-in, which provides a whole lot more functionality than JavaScript and operates inside Acrobat.
And thanks for the kind words about our site www.pdfscripting.com
Copy link to clipboard
Copied
We were not too keen on developing in VS2010 while 2017 libraries were around Thom. Sounded like trouble to us. Acrobat SDK has dependencies on VS2010 runtime and development environments.
Copy link to clipboard
Copied
I have plug-ins I developed on VS6 that work fine on Win10 and Acrobat DC. The SDK/VS dependancies are only for the development environment, they don't affect actual operation. You just have to pick the SDK that fits you current version of VS.
Copy link to clipboard
Copied
Thom have you developed any acrobat plug-in using VS2017? This is what I read recently about using VS2017 - Can Plug-Ins be Created With Visual Studio 2017? I will bring up the possibility of installing VS2013 and developing in that toolset in our next planning session.
Copy link to clipboard
Copied
I have not used VS 2017 with the SDK, but I have written plug-ins with many, many other versions of VS, going back to Acrobat 5 and VS6. If you want the VS and SDK tools to mesh nicely, then you need to match the SDK version to the VS version, although there is a great deal of compatibility between VS versions. MS is not in the habit of yanking their developers around. However, in the end, the plug-in that is generated with the tools will be compatible with a very wide range of Acrobat versions. There is an Acrobat version compatibility define that determines what elements of the SDK are allowed. You set this for backwards compatibility.
Copy link to clipboard
Copied
Let me add a couple more things to what Thom has said (and, my plugin development experience goes back even further than Thom’s )
Even though there is anecdotal evidence that you can develop a plug-in with a version of VS that is different from what Adobe specifies, IMHO it is a bad idea to do that, unless you know exactly what you are doing. Getting your first plug-in to complile and to load correctly is hard enough with the supported VS environment, without that, you will very likely not find any help here, because the chances that somebody uses the same configuration as you are pretty slim.
As far as how to best approach this, I would (and actually do) use a virtual machine for your plug-in development. This way, you are not installing another version of VS on your system, and you can also be sure that nothing that is already on your system will interfere with the plug-in development.
Copy link to clipboard
Copied
Thanks for looking in on this thread Karl. Your observations on keeping build toolsets distinct are very valuable and I can see why a VM would be helpful. My next task is to examine the sdk dependencies while we build a .js prototype.