28 Replies Latest reply on Jan 21, 2012 6:51 AM by richardh6

    Shared Hyperlink Destination

    Doug.Norton Level 1

      I'm creating a hyperlink using:

       

      var myHyperlinkURL = myDocument.hyperlinkURLDestinations.add("http://abc.com", {name:"abc"});

      var myHyperlinkSource = myDocument.hyperlinkTextSources.add(app.selection[0]);

      var myHyperlink = myDocument.hyperlinks.add(myHyperlinkSource, myHyperlinkURL, {visible:false, hidden:false, name:"ABC Link"});

      It works but it creates it as a "shared hyperlink destination". How do I make one that isn't shared?
      Thanks
      Doug

        • 1. Re: Shared Hyperlink Destination
          Jason Mohr Level 1

          I'd love to know if anyone has a script to convert urls to hyperlinks that does NOT make them all shared links.

          • 2. Re: Shared Hyperlink Destination
            John Hawkinson Level 5

            Have you tried generating a unique name for the destination? Perhaps with Math.random or a sequential counter?

            • 3. Re: Shared Hyperlink Destination
              richardh6 Level 1

              I am having the same problem.

               

              When you use a script create new hyperlinks without specifically assigning an already existing destination to the new hyperlink, InDesign creates a new unique destination for you with a unique name, so you don't even need to set your own unique name. This is fine for most purposes. But the problem remains that it is still a shared destination, so that if you copy and paste some text containing one of these hyperlinks, both versions will point to the same shared destination, so that if change the URL of one you are changing the URL of the other.

               

              Does anybody know how to create a new hyperlink, using a script, that has the same behavior as a new hyperlink created in the UI with "shared destination" unchecked? I can't figure out for the life of me where in the object model this option resides.

               

              Thanks.

              • 4. Re: Shared Hyperlink Destination
                richardh6 Level 1

                I have figured out what's going on -- sort of -- but I haven't figured out how to fix it.

                 

                 

                It turns out that every hyperlinkURLDestination has a property called "hidden." In Adobe's Object Model Viewer, it says the following about this property: "If true, the hyperlink is hidden."

                 

                 

                This is incorrect and misleading. You can easily create a document in which all of the hyperlinks are not hidden, but some of the hyperlink destinations are hidden, so this property clearly has nothing to do with the hyperlinks.

                 

                 

                What it does have to do with is this: it appears to be the flag that tells you if that destination is shared or not. If hyperlinkURLDestination.hidden === true, that destination object will not be treated as shared. Which means that if you copy and paste a link that points to that destination object, the new link will NOT point to the old destination object. Instead, a new destination object will be created, and the destinationURL string will be copied from the old destination object to the new destination object. The "hidden" property of the new destination object is also not shared.

                 

                 

                Conversely, if the "hidden" property is false, then that hyperlinkURLDestination is treated as shared, and if you copy and past a hyperlink that points to that destination object, no new destination object will be created; the new hyperlink will point to the existing destination object.

                 

                 

                The infuriating thing is this: hyperlinkURLDestination.hidden is a read-only property, and there doesn't appear to be any method to set it.

                 

                 

                Any ideas?

                • 5. Re: Shared Hyperlink Destination
                  richardh6 Level 1

                  Sorry, in the last sentence of the fourth paragraph above, I meant to say 'The "hidden" property of the new destination object is also TRUE.'

                  • 6. Re: Shared Hyperlink Destination
                    MatthewMariani Level 1

                    How about this?

                     

                     

                    var myDocument = app.documents[0];
                    var myHyperlinkURL = myDocument.hyperlinkURLDestinations.add("http://www.adobe.com", {name:Math.random().toString(), hidden:true});
                    var myHyperlinkSource = myDocument.hyperlinkTextSources.add(app.selection[0], {name:Math.random().toString()});
                    var myHyperlink = myDocument.hyperlinks.add(myHyperlinkSource, myHyperlinkURL, {visible:false, hidden:false, name:"http://www.adobe.com"});
                    
                    
                    1 person found this helpful
                    • 7. Re: Shared Hyperlink Destination
                      richardh6 Level 1

                      Thank you Matthew, that totally works.

                       

                      I did not know that we can set read-only properties, as long as we set them when the object is being created. That's a little strange.

                       

                      I guess you learn something new every day.

                       

                      By the way, you don't need to do that Math.random() thing with the names. InDesign will automatically add new unique destination names if you don't specify them. Same with hyperlinks.

                       

                      I also discovered another thing that the hyperlinkURLDestination.hidden property does: it prevents the destination from showing up in the UI when you go to "hyperlink destination options." It's still there when you check it with a script, and it still has a name, but it won't show up in the UI at all. Which kind of fits a little better into the meaning of the word "hidden."

                       

                      Mystery solved.

                      • 8. Re: Shared Hyperlink Destination
                        MatthewMariani Level 1

                        Your insights pointed me to the solution, but I wouldn't mind if you pushed the button to credit me a few points.

                         

                        I know you don't need the Math.random() thing, but I just think it's cool.

                        • 9. Re: Shared Hyperlink Destination
                          richardh6 Level 1

                          I take that back, I was wrong: you do have to add new hyperlink destinations with random names. When it copies a link, it creates a new destination object but that destination object has the same name property. You'll probably never need to use it, but just in case you need to identify one of them by name, you might as well do that random name thing.

                           

                          This is still not true of hyperlinks themselves or of hyperlink sources. They always have distinct names if you don't set them yourself. These are much more visible in the hyperlinks palette in the UI, so you might want to set them anyway, but you don't have to.

                          • 10. Re: Shared Hyperlink Destination
                            MatthewMariani Level 1

                            Good to know. thanks!

                            • 11. Re: Shared Hyperlink Destination
                              richardh6 Level 1

                              Matthew,

                               

                              Yeah, I looked for that credit button but I couldn't find it! Maybe I'm not looking hard enough, but I think that only the original asker of this question can declare your response "helpful" or "correct."

                               

                              Thanks again, though.

                              • 12. Re: Shared Hyperlink Destination
                                richardh6 Level 1

                                And yes, it was a group effort. That's what I like about this forum.

                                • 13. Re: Shared Hyperlink Destination
                                  [Jongware] Most Valuable Participant

                                  I simply add the count of hyperlinks. That oight be be more unique than any old random number :-)

                                  • 14. Re: Shared Hyperlink Destination
                                    TᴀW Adobe Community Professional & MVP

                                    (Your English is getting curiouser and curiouser!)

                                    • 15. Re: Shared Hyperlink Destination
                                      [Jongware] Most Valuable Participant

                                      It's just the one-fingered typing on my iPad :-/

                                       

                                      Oh & I'm not a native speaker either, that might account for the odd expression 's well.

                                      • 16. Re: Shared Hyperlink Destination
                                        richardh6 Level 1

                                        Matthew's method has been working for me for the creation of new hyperlinks, but what about existing ones, like ones that you import from a Word document? Does anybody know a way to set the read-only "hidden" property in the destination object?

                                         

                                        Of course, one could save the important information and then remove the hyperlink entirely, then recreate it the way you want it, but that seems like a lot of trouble (and this version doesn't even test for missing sources and destinations):

                                         

                                         

                                        Hyperlink.prototype.recreate = function( props, /* bool */ sharedDest ) {
                                        
                                          var src, dest, name, destHidden, destName, srcText, destURL, link;
                                          var doc = this.parent;
                                        
                                          // Save important info
                                        
                                          src = this.source;
                                          dest = this.destination;
                                          name = this.name;
                                        
                                          srcText = src.sourceText;
                                        
                                          destURL = dest.destinationURL;
                                          destHidden = dest.hidden;
                                          destName = dest.name;
                                        
                                          // Remove old hyperlink
                                        
                                          this.remove();
                                          src.remove();
                                        
                                          // if the destination was hidden, removing the hyperlink will remove the destination
                                          // and if you try to remove it again an error will be thrown, so check to see if it's hidden before removing it.
                                        
                                          if (!destHidden) dest.remove();
                                        
                                          // Create new hyperlink
                                        
                                          dest = doc.hyperlinkURLDestinations.add( destURL, {name: destName || Math.random().toString(), hidden: !sharedDest} );
                                          src = doc.hyperlinkTextSources.add ( srcText );
                                        
                                          link = doc.hyperlinks.add( src, dest, props );
                                          link.name = name || srcText.contents.slice( 0, 20 );
                                        
                                          return link;
                                        };
                                        
                                        
                                        // -------- TEST (need to have an existing hyperlink called existingHyperlink)------------
                                        
                                        var DEFAULT_HYPERLINK_PROPERTIES = {
                                          borderColor: [183, 27, 23],  // Burgundy, roughly.
                                          borderStyle: HyperlinkAppearanceStyle.DASHED,
                                          width: HyperlinkAppearanceWidth.THIN,
                                          visible: true,
                                        };
                                        
                                        var newHyperlink = existingHyperlink.recreate( DEFAULT_HYPERLINK_PROPERTIES, false );
                                        
                                        • 17. Re: Shared Hyperlink Destination
                                          scholarlyauthor Level 1

                                          I am trying something similar and cant get it to work, I have been reading over the documentation for days and am just trying to figure out how to add an anchor to a paragraph style in javascript. This is what I have so far:

                                           

                                           

                                          function main(){

                                          var myDoc = app.activeDocument;

                                          var num_pars = myDoc.stories[0].paragraphs.length;

                                           

                                           

                                          for (i =0; i<num_pars; i++) {

                                              if( myDoc.stories[0].paragraphs.item(i).appliedParagraphStyle.name == "Title" ) {

                                          aText = app.activeDocument.stories[0].paragraphs[0];

                                          aDest = app.activeDocument.hyperlinkTextDestinations.add(aText,{name:aText.co ntents});

                                          }

                                          }

                                          }

                                           

                                          What am I doing wrong?

                                          • 19. Re: Shared Hyperlink Destination
                                            jeremiah-swanson Level 1

                                            I have a similar problem with shared hyperlink destinations. It appears that there is the possibility of a document containing a hyperlink that was copied from another document and when you look at the properties of the copied hyperlink (in InDesign) it shows the original document the hyperlink is contained in. This poses a problem as when trying to access the hyperlink in server scripting. The server has no reference to the original document (and its contents, including the copied hyperlink) so there is a missing destination for the hyperlink. This is a HUGE problem because if you even attempt to access the copied hyperlink destination it completely crashes InDesign Server. In my case I need to access the destination of the url to perform processing on.

                                             

                                            I have been looking at this for days and have been unable to find a way to approach this problem, short of telling users to NOT create shared destination hyperlinks but you can't count on them always doing this, not to mention all the current documents that might contain a copied hyperlink.

                                            • 20. Re: Shared Hyperlink Destination
                                              richardh6 Level 1

                                              This method changes the 'hidden' property of the hyperlink's destination property. The 'hidden' property is what determines whether the destination will be shared or unshared. It's a read-only property so you can't normally change it, but it can be set when you create a new destination, so this method actually takes the old destination, deletes it, and recreates it.

                                               

                                              To use this method in your case in the background, I supposed you'd have to have an event listener run it every time you opened a document, or something. Or you could just run it manually whenever you needed it.

                                               

                                              Hyperlink.prototype.changeDestinationSharing = function( shared ) {
                                              
                                                var newDestHidden = !shared;  
                                                var doc = this.parent;
                                              
                                                var dest = this.destination;
                                                if (!dest) {
                                                  throw new Error("This hyperlink is missing its destination.");
                                                }
                                              
                                                var destURL = dest.destinationURL;
                                                var destName = dest.name;
                                                var destHidden = dest.hidden;
                                              
                                                // If the shared status of the existing destination does not
                                                // match what we want, remove the old one and replace it with a new one.
                                              
                                                if (destHidden !== newDestHidden) {
                                                  dest.remove();
                                                  dest = doc.hyperlinkURLDestinations.add( 
                                                          destURL, {name: destName || Math.random().toString(), hidden: newDestHidden} );
                                                  this.destination = dest;
                                                }
                                              };
                                              
                                              // -------- TEST (need to have a hyperlink called existingHyperlink)------------
                                              
                                              try {
                                                existingHyperlink.changeDestinationSharing( true );
                                              } catch(e) {
                                                alert(e.message);
                                              }
                                              
                                              
                                              • 21. Re: Shared Hyperlink Destination
                                                jeremiah-swanson Level 1

                                                Hey Richard,

                                                 

                                                Unfortunately this does not work in my scenario. When trying to reference the destination of the hyperlink in the following line copied from above -

                                                 

                                                var dest = this.destination;

                                                 

                                                InDesign client software actually opens up the document the original link was located in, and then can reference the properties of it. On InDesign server however this is not the case. InDesign Server seems to not know what do to since the hyperlink info isn't in the open document. It sits there and hangs on the line of code above and eventually crashes with a faulting module of hyperlinks.rpln. I've tried using your block of code above with no success (on InDesign Server that is). It is a useful script though and would work quite well with client InDesign.

                                                 

                                                I'm trying to figure out a way programmatically to avoid this situation. Since I am unable to reference the shared link in InDesign Server I'm at a loss on how to do this. Also I should mention this works fine if the shared hyperlink is in the containing document. This only seems to happen when the hyperlink was copied from another document, and for some reason InDesign references the other document for the link info.

                                                 

                                                Thank you for your post though, it does provide some good insight on how the hidden property works.

                                                  

                                                 

                                                 

                                                 

                                                • 22. Re: Shared Hyperlink Destination
                                                  richardh6 Level 1

                                                  Wow, that's really unfortunate. Sounds like you need to talk to the people who make InDesign Server.

                                                   

                                                  One last interesting thing, by the way, about the Hyperlink.destination.hidden property, is that when you delete a hyperlink, its destination will be deleted along with it ONLY IF THAT DESTINATION IS SHARED.  So I have another method that deletes hyperlinks along with their destinations, but once you delete the hyperlink, you have to remember to only try to delete the destination if it was shared. Otherwise it will throw an error.

                                                  • 23. Re: Shared Hyperlink Destination
                                                    John Hawkinson Level 5

                                                    Unfortunately this does not work in my scenario. When trying to reference the destination of the hyperlink in the following line copied from above -

                                                     

                                                    var dest = this.destination;

                                                    Are you aware that you cannot use that line by itself? this is only meaningful inside a constructor instantiated with the new operator. Did you call new on the constructor first?

                                                    • 24. Re: Shared Hyperlink Destination
                                                      jeremiah-swanson Level 1

                                                      Yes, I'm fully aware that you cannot use that line by itself. The block of code works fine in client InDesign, just not on InDesign server and when it is a hyperlink copied from another document.

                                                      • 25. Re: Shared Hyperlink Destination
                                                        richardh6 Level 1

                                                        this is only meaningful inside a constructor instantiated with the new operator.

                                                         

                                                        This is true in general, but for practical purposes, it's important to point out that most objects in InDesign (hyperlink objects in this case) that people will be using will either already exist in the document when the script runs, or they will be created by the 'add' method of the corresponding InDesign collection object, which uses the new operator in the background (or something that has the same effect -- I don't know the technical details of the implementation of the 'add' method), but the script writer doesn't directly use it. (I know you both know this -- I'm just writing for other people who happen to read this thread that might not know it.)

                                                        • 26. Re: Shared Hyperlink Destination
                                                          John Hawkinson Level 5

                                                          Sorry, Richard, I should have been more clear.

                                                           

                                                          My point was the vast majority of InDesign Javascript users ignore classical inheritance and write code that directly manipulates objects without caring about inheritence, be it classful or prototypal. So a typical function in that paradigm might be

                                                           

                                                          function checkDest(link, shared) {
                                                            ...
                                                            var dest = link.destination;
                                                            ...
                                                          }
                                                          

                                                          and in such case, you could pull out the reference to the destination property and use it elsewhere, and hopefully it would be clear that link was a formal parameter to the function. I was concerned that those unfamiliar with the inheritence situation might presume that it was appropriate to use 'this' outside of the strict confines of prototypes.

                                                           

                                                          Perhaps that worry was unnecessary -- certainly my poor expression of it generated excessive confusion!

                                                          • 27. Re: Shared Hyperlink Destination
                                                            scholarlyauthor Level 1

                                                            Why can't multiple links go to the same place?

                                                             

                                                            For example, a document discussing chess.com would mention chess.com a lot and be hyperlinked?

                                                            • 28. Re: Shared Hyperlink Destination
                                                              richardh6 Level 1

                                                              Actually, multiple links can all go to different objects that all contain the same URL.

                                                               

                                                              In your chess.com example, if we have set up our links to NOT use shared destinations, then the destination PROPERTIES of the multiple hyperlink objects are pointing to different destination OBJECTS, each of which has a destinationURL property whose value happens to be the same in every case: the string "http://www.chess.com".

                                                               

                                                              This means that each of these destination objects occupies a separate place in memory, and each of them contains a destinationURL property which is a separate copy of the string "http://www.chess.com". This is a slight waste of space, which is probably why InDesign makes shared destinations the default.

                                                               

                                                              In a shared destination situation, each of the hyperlink objects' destination properties points to a SINGLE destination object in memory, which has as its destinationURL property the string "http://www.chess.com".

                                                               

                                                              It saves a tiny bit of space, but there are many reasons why the shared destination situation could cause problems. The main two I can think of are that

                                                               

                                                              • (Jeremiah's main problem) If a hyperlink's destination property points to a shared destination object that is actually in another DOCUMENT -- because someone has copied and pasted the link from there -- then InDesign will have to open that document (or exhibit even worse behavior in InDesign Server -- see the posts above) to access the destination object and its destinationURL property, which is very often not what we want to have happen, and

                                                               

                                                              • (My main problem) If all the hyperlinks' destination properties are pointing to a single shared destination object and somebody decides that one of the paragraphs in your example should be talking about checkers and not chess, and after editing all the text (including changing the link text to "checkers" or "checkers.com") they also use the Hyperlinks palette to change the URL for the hyperlink in that paragraph to "http://www.checkers.com", then what they have actually done is to change the destinationURL property of the SINGLE shared destination object. Now all the hyperlinks in the entire document have destination properties that point to ONE destination object whose destinationURL property happens to be "http://www.checkers.com", even though all but one of the hyperlinks' sourceTexts still contain the word "chess," or "chess.com".

                                                               

                                                              These are some of the reasons why we want to find a way to have unshared hyperlinks be the default.