7 Replies Latest reply on Feb 23, 2012 8:51 AM by DHeadrick

    Code to destroy annotations doesn't seem to be executed

    DHeadrick Level 1

      Hi,

       

      My PDF document contains JavaScript that removes annotations as one of its initialization steps.  This is because the main body of the program creates numerous annotations.  If the user saves the PDF document (against the advice I provide), the just-created annotations will all be saved within the document.  When the user next opens the document, the just-saved annotations will still be there and then the program will create new annotations, which will be "overlaid" on the existing annotations.

       

      So, I've added the standard annotation-destroying code during my JavaScript initialization that everyone seems to use:

       

          var annots = this.getAnnots( { nPage:0} );  // my document only has 1 page

          if (annots != null)

          {

            console.println("Annots @ entry = " + annots.length);  // print the number of annotations to be deleted

            for (var i = 0; i < annots.length; i++)

               annots[i].destroy();

          }

       

      The problem is that the above code isn't executed during initialization, and the number of sets of annotation embedded in the document just keeps climbing each time I open/save the document.

       

      I can force the JavaScript to be re-executed by doing the following (in Acrobat 9):

       

            Advanced > Document Processing > Document JavaScripts...

       

      This brings up the "JavaScript Functions" dialog.  When I close this dialog, the JavaScript is re-executed and the annotations are all deleted as evidenced by the console.println statement displaying how many annotations are deleted.

       

      So, my question is: How do I make sure that the annotation-destroying code is executed when I open the document each time?

       

      By opening/saving/closing the document 10 times, it will create 10 sets of duplicate annotations in the document.  Only when I bring up and then close the "JavaScript Functions" dialog will the 10 sets of annotations be deleted as evidenced by the console.println statement.  Of course, my Adobe Reader-based users won't have this option.

       

      I think my question translates into: How do I make sure that the JavaScript engine correctly recognizes that there are pre-existing annotations when I open my PDF document?  Currently, this recognition only seems to occur when I use the "JavaScript Functions" dialog to re-excute my code.

       

      Thanks for any insights anyone has regarding my question!

       

      Dave

        • 1. Re: Code to destroy annotations doesn't seem to be executed
          try67 MVP & Adobe Community Professional

          Try calling this.syncAnnotScan() before running the rest of your code.

          • 2. Re: Code to destroy annotations doesn't seem to be executed
            George_Johnson MVP & Adobe Community Professional

            I hope everyone doesn't use that code as it contains a classic programming mistake. In addition to try67's good advice, you need to start at the last index and delete up to the first:

             

             

            syncAnnotScan();
            var annots = this.getAnnots({nPage:0});
            
            if (annots) {
            
                var num = annots.length;
            
                for (var i = num - 1; i > -1; i--) {
                   annots[i].destroy();
                }
            }
            
            1 person found this helpful
            • 3. Re: Code to destroy annotations doesn't seem to be executed
              try67 MVP & Adobe Community Professional

              Good catch, George.

              I think that this approach works as well:

              for (var i in annots) annots[i].destroy();

              • 4. Re: Code to destroy annotations doesn't seem to be executed
                DHeadrick Level 1

                Hi,

                 

                Wow, what a great response!!  I had never seen this.syncAnnotScan() before.  The description says "In general, you should call this method if you want the entire list of annotations", which I certainly do.

                 

                So, I put this call before my annot-destroying code and it works perfectly -- everytime I save my PDF (which contains my embedded annotations) and then re-open it, my console.println statement (from my original posting) prints out the correct value for annot.length (based on my code) and then proceeds to destroy all of them.

                 

                So, I'll mark try67's first response as the Correct Answer.

                 

                Regarding the implementation of the annot-destroying code, I have a question for George.  What is the purpose of deleting starting at the last index and deleting up to the first?  If you do it my original way, does annot.length change "on the fly" as annotations are deleted?  If so, I could understand why it would be good to "lock down" annot.length as you did by equating it with "num" up front.  However, the advantage of deleting starting at the last index isn't clear -- your thoughts on this?

                 

                Thanks again for everyone's help with my question, it's always nice to get such a prompt, concise and usable answer!

                 

                Dave

                • 5. Re: Code to destroy annotations doesn't seem to be executed
                  George_Johnson MVP & Adobe Community Professional

                  That's a good question, because what I stated and implied apparently isn't necessarily the case with annotations. It is with things like pages and form fields, but annotations must be implemented differently, and is the reason for the existence of syncAnnotScan. In general though, the correct way to delete indexed objects in a for type loop is to start at the end and move to the beginning.

                   

                  Edit: corrected typo

                  • 6. Re: Code to destroy annotations doesn't seem to be executed
                    try67 MVP & Adobe Community Professional

                    I think the reason it works with annots is that you're saving the annots array into a variable, which is not being updated on the fly.

                    So destroy an annot doesn't affect the length of the array, and therefore it works.

                    If you had used something like this:

                     

                    // INCORRECT CODE -- DO NOT USE

                    if (this.getAnnots({nPage:0})) {

                        var numAnnots = this.getAnnots({nPage:0}.length;
                        for (var i=0; i<numAnnots); i++) {
                          
                    this.getAnnots({nPage:0})[i].destroy();
                        }
                    }

                     

                    It would have behaved strangely. Probably would have only deleted half of the annotations and would throw an exception at the end because of an out-of-bounds-index.

                    Generally speaking, when deleting items from an array, one should always start from the last element going backwards, or use an Iterator object.

                    • 7. Re: Code to destroy annotations doesn't seem to be executed
                      DHeadrick Level 1

                      Thanks for the further information.  I learn something new each time one of you does a reply!