Thom Parker
Community Expert
Thom Parker
Community Expert
Activity
‎Jun 12, 2017
05:10 PM
I'm glad you were able to deal with it so quickly. A very common issue. Windows hides a lot of folders and file info that's needed for PDF development. I usually run into this issue with folder level JavaScript files, because Acrobat hides the ".js" file extension. So it's also a good idea to uncheck "Hide file extensions" in the folder options. And if you think the issue is answered, then please mark it as so.
... View more
‎Jun 12, 2017
03:55 PM
There is a video on this topic here: https://www.pdfscripting.com/public/images/Free_Videos/BeginJS_Console_Alt_mp4.cfm
... View more
‎Jun 12, 2017
03:55 PM
It's also called the JavaScript Debugger. You'll find a button for it on the JavaScript pane on the Tools Panel. It can also be displayed with "Ctrl-J".
... View more
‎Jun 12, 2017
11:35 AM
The intent of that article was to create a new stamp file, not modify the existing Acrobat Dynamic.pdf file. You were only supposed to copy functionality from the Dynamic.pdf file. Because, the act of inserting your page into this file destroys the dynamic stamp info on the file you insert. However, that doesn't explain why Dynamic.pdf stopped working. Something else must have been done to it. Regardless, if you used the "Stamp Manager" in Acrobat to create a new stamp, then that stamp will be in a file with a cryptic name, in the "user" stamp folder. To locate this folder, run the following code from the Acrobat Console Window. app.getPath("user","stamps"); You can find out more info in this AcrobatUsers tutorial: https://acrobatusers.com/tutorials/dynamic_stamp_secrets
... View more
‎Jun 12, 2017
11:23 AM
Well Actually, you ought to be able to use an URL in a PDF link with the "javascript:" prefix. This will of course cause Acrobat to have a small fit and display lots of security popups. A much better solution is to pass your desired parameters in a query string to a web app that will in turn display the page correctly.
... View more
‎Jun 12, 2017
11:08 AM
2 Upvotes
Tough problem, especially on the iPad. Mobile devices are tricky because the JS options are severely limited on the good viewers, and there are lots of really crappy PDF viewers that don't even recognize form fields, much less execute code. First, I'd suggest you use the Readdle PDF Expert or Adobe Mobile Reader on the iPad. Readdle is the best, it has much better submit and JavaScript functionality than any other App. Next, write the script on the regular Acrobat Pro on your desktop. if(1 == app.alert("increment?",2,1)) this.getField("Agreement").value = this.getField("Agreement").value + 1; Put this in a document script and test it out. If it works for you on the desktop, try it on the iPad with the two PDF viewers I've mentioned above. If it works, then you have something. However, you may find this technique problematic, but cause it's all on the client. There is no way to know if the number hasn't already been used, or if a number is skipped. This is especially true if there is more than one iPad doing the submit. A much better methodology is to use a "presubmit", to the server script that is doing the form processing, and have it search the DB and return an FDF with the correct next number. Only the Readdle Viewer can do this. Alternatively you can use a psuedo random number generator to create unique IDs. Then all these other issues go away.
... View more
‎Jun 12, 2017
10:45 AM
In general it is best not to edit the files that come with Acrobat. You may be able to recover the original file from the "Help->Repair Installation" menu item Now, what specific actions is you apply to the stamp file? please be specific.
... View more
‎Jun 12, 2017
10:02 AM
1 Upvote
I'm with JR on this one. True DRM is expensive and unwieldy. The OCG solution is cheap, easy, and cracking it is beyond the technical abilities of nearly all users. I have customers that uses this technique with documents they sell. So it really works. I've got a demo file that provides detailed instructions on my site. However, it does fall in to the category of keeping honest users honest. Rather than preventing malicious users from accessing the PDF. Toward this end the solution can be made stronger by also encrypting the PDF with a self signed certificate from the target user. I think this is a pretty good combination, blocking OCG Layer and digital certificate encryption.
... View more
‎Jun 10, 2017
08:41 AM
So, the "this.closeDoc(true) statement is in the stamp script or the menu script? Is there are an error reported in the console window? The console is the first place to look whenever there is a JavaScript issue. closeDoc(true) changes the state of the document. This can be dangerous when the document is being operated on by the script. In the stamp script "this" refers to the stamp itself, so I doubt Acrobat would allow it to be run, and it if did it might crash Acrobat cause you're closing the stamp file in the middle of applying the stamp. If it is run from the menu script, then "this" may or may not refer to the document being stamped. It is better to reference the document directly with "event.target". But even if "this" does point to the document being stamped, there may be other things happening with the PDF that would cause "closeDoc" to not work. So what's in the console window?
... View more
‎Jun 07, 2017
03:20 PM
Well you know, as Try67 says, the issue is with the storage location. But the important bit here is not the specific location, but the data. So, you can simply use a different location. For example, any global generic object. It's important that the object is both global and generic, so that it can be seen everywhere and handled generically. For example the "color" object. Just replace "event.source.source.info" with "color" and see how that works.
... View more
‎May 30, 2017
03:03 PM
Yes, this is the correct methodology, except you should name the info property for the data. event.source.source.info.Supplier = Supplier; event.source.source.info.InvoiceNum= InvoiceNum; event.source.source.info.Company = Company; These make a lot more sense than "DocumentState". Also, instead of the "app.response" box, I'd use a custom dialog. Dialogs however are much more difficult to create than the code we've just worked though.
... View more
‎May 30, 2017
01:38 PM
try67 wrote .. It's sounds like a bit of a mess to write such a code, though. Compared to what? writing a plug-in? If you can get away with a funky JS solution, then it is a better solution than creating a plug-in for the simple reason that it's fast, easy, and will work across platforms, and even in many 3rd party tools (except when menu items are used). That is not to say that I don't create a lot of single purpose plug-ins for filling in the holes in the JS model. But you have to be very careful for exactly the same reasons I've mentioned above, i.e. Plug-ins activated from JS operate asynchronously.
... View more
‎May 30, 2017
01:30 PM
First, My Bad. I just copied your code for the "mySaveProc" and forgot to remove the inputs Here is the revised code var mySaveProc= app.trustedFunction(function() { app.beginPriv(); var myDoc = event.target; var myPath = "/c/" + myDoc.info.DocumentState + "/test.pdf"; myDoc.saveAs(myPath); app.endPriv(); }); Now, about the "Supplier" value. In the stamp script you have this line: event.source.source.info.DocumentState = Supplier; This code places the "Supplier" data value into "doc.info.DocumentState" where "doc" is a pointer to the document object in question. In this case the document being stamped. Check on it. Open the Document Properties window and click on the custom tab. You'll see the value there. "myDoc.info.DocumentState.Supplier" is not a thing. It does not exists, because the code only sets "myDoc.info.DocumentState". Go with the code for "mySaveProc" as I've written it above.
... View more
‎May 30, 2017
12:10 PM
I've created many tools that use the "NewBookmark" menu item to create bookmarks. It is the only way from JS to create bookmarks with destinations. But it is tricky because of timing issues. The bookmark is not created synchronously when "app.execMenuItem" is called. The menu item execution happens asynchronously. So the newly created menu item may not be available to JS code for an unknown amount of time. So it's best not to look for then new item right after creating it. The technique described below handles this issue by creating and manipulating the bookmarks in different loops. Not perfect but it usually works. To create the bookmark tree with JavaScript you'll need to know the pattern of the tree up front. The most important bit is the pages that need bookmarks. As a simple example, you could use an array, where each entry in the array is another array containing the zero based page number and a name. like this: var BKData = [ [0,"title page"], [1, "TOC"], [5, "intro"] ] The code should work as follows: 1. Loop on array to create a flat set of unnamed bookmarks for(var i=0;i<BKData.length;i++) { this.pageNum = BKData[0]; app.execMenuItem("NewBookmark",this); } 2. Loop on bookmarks to set names var bkMarks = this.bookmarkRoot.children; for(var i=0;i<bkMarks.length;i++) { bkMarks.name = BKData[1]; } The "NewBookmark" menu item creates the new bookmark at the bookmark with the current focus. The assumption in this code is that there are no bookmarks initially, so the new bookmarks are created from the top in order in which they appear in the "BKData" array. And they are the only bookmarks in the document. You can make this much fancier by putting hierarchy data, such as a level number, into the "BKData", Then adding a 3rd loop to sort the bookmarks into the correct hierarchy.
... View more
‎May 30, 2017
10:04 AM
You are very close, but your code has a couple of problematic spots. 1. In the code that creates the menu item => cExec: "mySaveProc();", the function mySaveProc is called with no parameters, yet it has 2 inputs, This is not an error, just neatness, get rid of the two inputs. 2. In the "mySaveProc" function the "Supplier" parameter is undefined. What you want to use is the storage location for "Supplier", like this: var mySaveProc= app.trustedFunction(function(myDoc, myPath) { app.beginPriv(); var myDoc = event.target; var myPath = "/c/" + myDoc.info.DocumentState + "/test.pdf"; myDoc.saveAs(myPath); app.endPriv(); }); It also does not need to return a value. This will work, but if you have issues, report back and I'll show you how to do some debug
... View more
‎May 23, 2017
09:33 AM
event.value = Department event.source.source.info.DocumentState = Department; 2. save it to a common location, such as the document info. How can I do that ? Look at the line of code immediately above "2. save it to..." This code creates a new entry in the document info called "DocumentState". This new document info entry is accessed in the menu save script as "this.info.DocumentSate". Just as I showed in my previous post. You might want to go back and re-read what I've written.
... View more
‎May 23, 2017
08:22 AM
Looks pretty much identical to your hex code.
... View more
‎May 23, 2017
08:22 AM
That's what I'm doing too, only I have an app that does it for me, cause I make a lot of toolbar buttons. Here's the hex code: 0af9f9f909ffffff0afefefe09f1f1f10df8f8f827f7f7f746d2d2d26fb5b5b594a3a3a3a99a9a9aaaa4a4a48aacacac6fc2c2c246dedede27e8e8e80df8f8f809fefefe09f4f4f40afefefe09ffffff09fdfdfd09f6f6f60af6f6f61af0f0f051c8c8c89c9b9b9bd8838383f0747474e27f7f7fdf7d7d7de0838383e7747474f06b6b6bd87e7e7e9aa2a2a24acfcfcf15f1f1f10afefefe0afcfcfc09f5f5f508f9f9f909f7f7f71fe9e9e970cacacacf888888ed707070c298989896a5a5a571bbbbbb6dbababa6cc8c8c877c5c5c599a7a7a7cd858585eb7c7c7cc592929268c2c2c21ff1f1f10afafafa09f1f1f109fbfbfb1bfafafa70bebebed7878787df787878969f9f9f48e3e3e319efefef0bffffff0affffff09ffffff0bf9f9f91cefefef52d5d5d59ba5a5a5e87e7e7ed68787876cc1c1c118eeeeee09ffffff0ef7f7f752d2d2d2cf818181da7d7d7d7ebcbcbc29e2e2e211f6f6f60cffffff0af0f0f004fefefe04fafafa0bf1f1f110f7f7f711fcfcfc2edddddd92acacace7797979c98c8c8c4dcccccc0effffff2de7e7e7a79b9b9be96f6f6f90afafaf27f2f2f264d2d2d284b7b7b72de3e3e334e5e5e502e7e7e701f3f3f312ffffff2febebeb84c0c0c065c8c8c82ee7e7e79aa4a4a4ec7878789a9f9f9f27f6f6f64cd5d5d5e2818181c18f8f8f46dedede10efefefa3a7a7a7e5747474b09c9c9c80cfcfcf05d5d5d501dddddd2cdfdfdfb1a6a6a6e4727272a0a8a8a80ffcfcfc51d7d7d7cd888888d982828246d5d5d57abebebeee7474748aacacac12f7f7f70efbfbfb62cececed9878787ef727272d186868675cacaca73d6d6d6a4a2a2a2ef6f6f6fd88484845dd0d0d00bf7f7f71bf0f0f0999e9e9ef17979796fbdbdbda6a3a3a3dd7e7e7e69c6c6c60af8f8f810ffffff19ececec65ccccccde777777f46b6b6bf0797979f0797979ed6d6d6ddd86868661cccccc16f9f9f90af5f5f50bffffff77b6b6b6e773737393a8a8a8ab9f9f9fcb9494944fd6d6d60aededed09ffffff0ff7f7f715f3f3f365dbdbdbe3848484fd727272fe6e6e6ed88f8f8f48c7c7c713f5f5f50affffff0af4f4f40af8f8f86dbebebee07a7a7aaaa3a3a3aba4a4a4cb8d8d8d4fd3d3d309f9f9f909fafafa88bcbcbcbca6a6a643d0d0d06ad9d9d9ed919191eb95959539e6e6e646e8e8e8b99b9b9b88a5a5a50affffff0af4f4f46dc6c6c6df808080aaa4a4a4a7a4a4a4dc76767668c4c4c40affffff0affffff9fa6a6a6f0696969da88888875bbbbbb13d0d0d010dfdfdf41cbcbcbda909090ef6a6a6a9e9f9f9f0afbfbfb0afcfcfc70c0c0c0e27b7b7b93aeaeae84b1b1b1ec78787884b2b2b211ededed09f9f9f940d7d7d7ba949494ef6a6a6aea757575a0b5b5b59fbcbcbcd8797979f0616161bb9d9d9d40dfdfdf09f6f6f618f8f8f897a7a7a7f271717170bcbcbc58cececee87d7d7dbb9090903dd6d6d60afcfcfc0affffff3fd2d2d2ba969696ee797979f3696969f3686868ec7e7e7eb5a2a2a241d1d1d109f7f7f70bffffff46d7d7d7c28c8c8cdf7c7c7c4ad0d0d02ee6e6e6ac949494e776767685b9b9b91df3f3f309ffffff0afafafa3fe5e5e5a79e9e9ee27b7b7be2828282a3afafaf30dadada0afefefe09ffffff24e6e6e692a5a5a5ea8181819ca5a5a527e9e9e910fafafa5fcacacada7a7a7ad982828276bababa1ce2e2e209fafafa09f8f8f825ededed77bcbcbc77c0c0c025e9e9e90afafafa0cffffff21e9e9e97bb8b8b8df818181cf83838352cdcdcd0efefefe09fafafa21eaeaea85b7b7b7e37c7c7cd979797984afafaf3ce2e2e210f2f2f20afefefe09ffffff0afcfcfc0afcfcfc12f7f7f747d6d6d690a5a5a5da868686d780808070bdbdbd1af4f4f40afefefe09f7f7f70afefefe2be9e9e986b2b2b2da818181e87c7c7cba97979784aeaeae68c3c3c34fd2d2d24fd3d3d369c4c4c48aabababc28d8d8dea7a7a7ad379797975c2c2c21ee3e3e30afefefe0afdfdfd0af1f1f10afbfbfb0affffff22f1f1f15fc6c6c6ac979797e77d7d7dec777777dd7b7b7bcb898989cb8a8a8adc7c7c7cee747474e37e7e7eaaa0a0a059c7c7c71ef5f5f509fafafa0afcfcfc0af9f9f90affffff0af6f6f60af6f6f60affffff0ffefefe2ee6e6e657c8c8c883b5b5b5a89e9e9eaaa5a5a5aba4a4a4a7a5a5a583b2b2b256c7c7c72fe2e2e20ffcfcfc09fefefe0af8f8f809f6f6f60af9f9f9
... View more
‎May 23, 2017
08:14 AM
Your current strategy has two steps. 1. apply the stamp with the regular stamp tool 2. use menu driven automation script to save file Let's stick with that for now. Forget what I said about putting it all in one script. You want the file information to be collected in one location, and then used for both the stamp and the save script. To do this, 1. collect the information in the stamp script. 2. save it to a common location, such as the document info. 3. the save script then uses this info to rename the document.
... View more
‎May 22, 2017
11:57 PM
The best thing to do is to ask all the questions in the menu script. Place the collected values into something that is accessible to the stamp script, then place the stamp. The stamp script then pulls the values from the common storage location. A good candidate for this storage is the document "info" object on the PDF being stamped. By default, the current document will be "this" when the menu item is selected. For example: // In the menu script this.info.myValue = app.response(cAsk, cTitle); // in the a field calculation Script on the stamp event.value = event.source.source.info.myValue;
... View more
‎May 22, 2017
11:24 PM
Here's what it looks like when I converted the PNG to an icon with the util.iconStreamFromIcon() function. I think it looks fine, but if you want the edges to be sharper, then you'll need to edit the original image, cause it does have slightly fuzzy edges.
... View more
‎May 22, 2017
07:52 PM
The test you described is an excellent demonstration of how the stamp is applied to the document after the stamp calculate script is finished running. In fact, in your example the app.alert box prevents the script from finishing, thus ensuring that the file will be saved without the stamp on it. Again the solution is to write an automation script that applies the stamp and then saves the document. Basically you need to extend the folder level script with a menu item or toolbar button to perform these two steps. I would suggest searching the internet for "how to make an Acrobat menu item", "Acrobat Automation Script" and "Automate PDF Stamp", "Apply PDF stamp with script", that sort of thing. We can certainly help with the next step.
... View more
‎May 22, 2017
02:38 PM
And the reason the file is named "undefined.pdf" is because of this line: var myFileName = event.source.source.Filename + ".pdf"; event.source.source refers to the document object being stamped, but there is no "Filename" property of the document object. It should be var myFileName = event.source.source.documentFileName + ".pdf"; Something that you should always do when writing code (any code for anything) is to verify the names of the things referenced in the code. For example, open the console window, enter and run this: this.Filename It will return "undefined" Now enter and run: this.documentFileName See what happens
... View more
‎May 22, 2017
02:33 PM
Ok, so if the "undefined.pdf" file did not exist before you placed the stamp, then you have shown that you can in fact save a PDF from a stamp script. This is very interesting because it shouldn't happen. But you have also proved my first point. Now please refer to my previous post: A stamp script, i.e., the code in the calculate script on a field on the stamp is very limited. It is run before the stamp is applied to the document. In order to save the file after the stamp has been applied requires a code to be run after the dynamic stamp has already finished running. The reason the stamp is not in this saved file is because the stamp does not exists when the stamp script is run. The save has to happen after the script is finished running. Hence the conundrum. The solution is to create an automation script that places the stamp on the PDF, then saves the file after the stamp is on the PDF.
... View more
‎May 22, 2017
01:48 PM
The global isn't for showing the dialog, its for defining the dialog object.
... View more
‎May 22, 2017
01:46 PM
The trusted function is needed to save, but the "app.trustedPropagatorFunction" is not necesary. That's all I as saying. Now, to get a clearer idea of what is happening in your current script, and in the future, please open the console window and see if any errors are reported. Let me know what you see and we'll go from there.
... View more
‎May 22, 2017
12:51 PM
Yes, you could add a menu or toolbar button, or a command, to set the options, but then you'd have both the action plus this thing. I find a better method is to create a summary document. That way the code is all contained in the action, much easier for the user to install. And the summary document is a visual reminder that everything processed is using the same parameters. As well as containing some useful info. For example, it can show status for document that can't be processed if there is security on the doc, or is XFA. The current code only checks the globals so it doesn't have to recreate the dialog each time.
... View more
‎May 22, 2017
12:30 PM
Did you try Math.round()?
... View more
‎May 22, 2017
12:27 PM
It looks like the poor image quality has to do with compression and scaling. What does the PNG (not the ps) file look like in PhotoShop?
... View more
‎May 22, 2017
12:23 PM
Gilad and Zimbop, the issue with action scripts is that the DOM provides no info about the file's order in the process. The script doesn't know if a file is the first in the process, or the last. Since the JavaScript model doesn't provide any info on this, then you have to create some method for detecting the first document. That's the trick.
... View more
- « Previous
- Next »