16 Replies Latest reply on Apr 20, 2011 5:26 PM by a.simonds

    Web Link Buttons with Variable URLs

    a.simonds

      Hey all:

       

      I asked my question earlier in the general InDesign section of the forum, but a helpful user suggested I repost it here as it will take some scripting magic to accomplish:

       

      My work assignment of late has been developing an interactive PDF catalog of our products that my superior can distribute digitally and let potential customers browse without accessing the website.

       

      We have an Excel file that lists all the details of our products - name, description, title, image, category, etc. I have used Data Merge to create this 300 page document rather than hand-copy each product's information to a single page.

       

      Unfortunately I am now stuck - I have designed the catalog in such a way that I have an image that I want to make a button which, if the person wishes to purchase a product, will take them directly the the product page online where he or she can add it to the shopping cart. This is great, but I cannot seem to find a way to make the image button's link a variable as the rest of the page content. Links to each product page are included in the CSV file, but without a variable web link method, I would have to create the unique links individually, which kinda defeats the purpose of using Data Merge anyway.

       

      So my question is this - is there any way to make a URL button (an image) have a web link function that can read from a CSV file and change each page like other imported content? If not, is there another way to automate the individual link process without setting it up on each generated page?

       

      Thanks in advance,

       

      Asher

        • 1. Re: Web Link Buttons with Variable URLs
          John Hawkinson Level 5

          Hi, Asher.

           

          You asked this question in the regular forum: Web Link Buttons with Variable URLs

          and I gave you an initial answer in that forum:

          var b, i, p, t,
              doc=app.activeDocument;
          for (i=0; i<doc.pages.length; i++) {
              p = doc.pages[i];
              b = p.buttons[0];
              t = p.textFrames[0];
              b.gotoURLBehaviors.add({ url: t.contents });
          }
          

           

          How does it fail to meet your needs?

          • 2. Re: Web Link Buttons with Variable URLs
            a.simonds Level 1

            Sorry for the late response. I am not really versed in Javascript and don't know exactly how to implement it. I copied the code into an ExtendScript window and it hung at the for loop, with the statusbar at the bottom saying "undefined is not an object."

             

            In the original thread you stated that these lines of code would work only if there was one textbox and one button on each page - there are at least 12 other buttons and 8 other textboxes/frames.

             

            Thanks for your help - this is really the last hurdle for this project to be finished.

            • 3. Re: Web Link Buttons with Variable URLs
              John Hawkinson Level 5

              Did you tell the ESTK to run your script in InDesign, rather than the script editor itself?:

               

              runswhere.png

              Well, you if you have more than one text box on the page, how is each button supposed to know which text box to use for a URL? You'll have to come up with some scheme.

               

              You can't expect the script to just read your mind...

              • 4. Re: Web Link Buttons with Variable URLs
                a.simonds Level 1

                I'm running the script in a test document right now, which was generated with a small CSV file (holds the links) and has one text box which holds the link in text and one blank buttton per page. The document is four pages long, each with the generated set of objects.

                 

                I have the script set now, and it hangs at

                 

                b = p.buttons[0];
                

                 

                I'm new at this whole scripting thing, but would assigning them scripting labels help?

                 

                UPDATE:

                 

                I had a friend look it over and he changed the brackets to parenthases and added .item to the b and t - now the code works with one textbox/button a page.

                 

                var b, i, p, t,
                
                    doc=app.activeDocument;
                
                for (i=0; i<doc.pages.length; i++)
                
                {
                
                    p = doc.pages.item(i);
                
                    b = p.buttons.item(0);
                
                    t = p.textFrames.item(0);
                
                    b.gotoURLBehaviors.add({ url: t.contents });
                
                }

                • 5. Re: Web Link Buttons with Variable URLs
                  John Hawkinson Level 5

                  Perhaps a screenshot of your page layout would help us to decide what the right way to handle this association is. Or perhaps someone else who actually uses these interactive features might chime in...

                   

                  The script...should not hang. Does it give you an error? An orange bar on some line? If so, it should tell you the error in the bottom left corner of the window.

                   

                  Not surprisingly, it works fine for me.

                   

                  Script labels might help, yes! It sounds like you're not as new as you sound!

                   

                  I'm not 100% how they'd interact with the data merge, but if there's only one button you need to fill in on each page [which is what it sounds like], then that should work fine. Alternatively, still if there's only one button, textFrames[0] should refer to the topmost ('Bring to Front') text frame. That might be a little fragile, but should probably work.

                   

                  Oh, I see your update. I can...think of no reason why that should be necessary, and frankly I dislike using the .item(n) form because it's more typing and uglier. But whatever floats your boat. Are you sure there weren't any other changes?

                   

                  Note that people who follow the forum via email won't see an update you add, so it's a good idea to make a new post if you have something significant to say...

                  • 6. Re: Web Link Buttons with Variable URLs
                    a.simonds Level 1

                    The new version my friend attended to works perfectly with the edits. As I mentioned in my last post the version you typed hangs (with the orange bar)at

                     

                    b = p.buttons[0];

                     

                    The console at the bottom line says "undefined is not an object"

                     

                    I run the script after the data merge is complete, since there is only one layout page before executing it (as well as there not being any content).

                     

                    I tried rearraging the button and text frame I want to target in the script just as you posted, and this works. But I agree, if there was a more direct way of doing it, I would prefer it.

                     

                    I understand basic code purpose and structure, but I don't have much of a clue on how to write it from scratch haha. How would I call script labels to identify the two objects directly? My friend is helping me on this one as well, but he knows javascript outright, and does not use InDesign at all.

                     

                    Thanks for the continuing help!

                     

                    BTW, here is a screenshot of your version running with the error:

                     

                    code2.JPG

                    • 7. Re: Web Link Buttons with Variable URLs
                      John Hawkinson Level 5

                      Huh, that error seems really mysterious. (I had assumed your initial problem was from targetting the ESTK instead of targetting ID, and when you said "hangs at the for loop" you meant the actual "for(..." line.) I'd be curious...if you run the broken version and after it hangs, try typing in the JavaScript console:

                       

                         p

                         p.buttons

                         p.buttons[0]

                         p.item(0)

                         p.buttons[0].id

                         p.item(0).id

                       

                      which ones work and which fail?

                       

                      In CS5, script labels got a bit more annoying to use. I think you might be better off using text box names instead.

                      Name the text box in the Layers panel by click-pause-click-ing it (wow, what an unfamiliar UI!) and assigning a name to it.

                       

                      Suppose you name it "url".

                       

                      Then instead of "p.textFrames[0]" (or p.textFrames.item(0)), you can use "p.textFrames.itemByName('url')".

                      Hopefully this doesn't get messed up across the data merge.

                       

                      To use the script label, you need this horrid construction:

                       

                      var j;
                      for (j=0; j<p.textFrames.length; j++) {
                          if (p.textFrames[j].label === 'url') {
                              t = p.textFrames[j];
                              break;
                          }
                      }
                      

                       

                      though if your InDesign is screwed up, you might need to change [j] -> item(j) again. Maybe you should Replace Your Preferences (http://forums.adobe.com/thread/526990).

                      • 8. Re: Web Link Buttons with Variable URLs
                        a.simonds Level 1

                        I am back home from work, but I Dropboxed the jsx file so I could tinker with it here. I recreated my test file (3 buttons - one used, three textboxes - one with the link) and tried your code again. Suddenly, it works! Both your code and my friend's variant worked. Soe something must be strange in the settings of InDesign at work.

                         

                        I added the name-specific code to the file and it worked through the first iteration of the loop, but stopped short. I named the text frame 'url' and the button 'urlbutton' - the problem is, buttons apparently need specific identifiers in the layers, and after a data merge (I have three links in the csv file, so it generates three pages and three sets of everything) the buttons add numbers to the layer name, so the code breaks. Naming and calling the text frame in the code allows it to find the right URL regardless of the layer order, but it unless there is another way to call the button regardless of its layer name, the button will have to be first.

                         

                        On the other hand, Script Labels are constant no matter how many copies there seem to be. Assigning the original urlbutton with "urlbutton" as a label will give the three generated buttons "urlbutton" as a label, unchanged. So unless there's another way (besides putting it as first button in layer order), I'd have to use the script label to identify the right button?

                        • 9. Re: Web Link Buttons with Variable URLs
                          John Hawkinson Level 5

                          Yeah, I think something was screwed up with your work machine, hence the suggestion to replace your preferences.

                           

                          I was afraid the naming might break. So you get to use the more complicated script code. Oh well. This is an annoyance a lot of people have with CS5, because prior to CS5, the syntax for finding items by label was the syntax we now use to find by name.

                           

                          There are lots of other ways, but the Script Label is probably best. You could depend on the z-ordering. You should search for a text frame that contains "http://". You could search for a textframe that contains "zaphod breeblebrox" and take the third word. You could find the textframe in a particular position on the page. Or containing a specific paragraph style. Or hundreds of other choices.

                          • 10. Re: Web Link Buttons with Variable URLs
                            John Hawkinson Level 5

                            Oh, sorry, I wasn't paying attention to the fact that you needed to

                            identify the buttons as well as the text frames. Though since buttons

                            do have names I suppose you could use a variant.

                             

                            Another good approach would be to put each button and textframe pair

                            in a group. Then you can iterate over the groups on the page and

                            take group.button[0] and group.textFrame[0] in each case.

                             

                            I think that might be the cleanest answer.

                            • 11. Re: Web Link Buttons with Variable URLs
                              a.simonds Level 1

                              So would the button version of the code you posted be this? And I'm assuming it'd go before the original part?

                               

                              var j;
                              for (j=0; j<p.buttons.length; j++) {
                                  if (p.buttons[j].label === 'urlbutton') {
                                      t = p.buttons[j];
                                      break;
                                  }
                              }
                              

                              • 12. Re: Web Link Buttons with Variable URLs
                                a.simonds Level 1

                                Whoops, didn't refresh the page.

                                 

                                A group you say? So the code would only look for available groups on each page, and since there would be only one - containing the text frame and the button - it'd automatically single them out? That sounds great!

                                • 13. Re: Web Link Buttons with Variable URLs
                                  John Hawkinson Level 5

                                  If you were using the aformentioned code to check the script label, it would have to go inside the for (i) loop, replacing the "b = p.buttons[0]" line. Though there was a typo because I set t to the button and instead I should have set b to the button.

                                   

                                  Yes, a group. If you know that there is only one group on the page, then you don't even have to loop over the groups. Instead you can just use:

                                   

                                  t = p.groups[0].textFrames[0];
                                  b = p.groups[0].buttons[0];
                                  

                                   

                                  Of course, that'll break if there's ever more than one group.

                                  • 14. Re: Web Link Buttons with Variable URLs
                                    a.simonds Level 1

                                    I think we have a winner! I tried the group at the top of the layer list, somewhere in the middle, and at the bottom in a whole new layer, and running the script successfully transferred the link codes to the URL of the button.

                                     

                                    I remember you put at the bottom of one of your posts in the original thread that there was a way to delete the text frame. How would I implement that in the script, and would it be affected by the grouping?

                                    • 15. Re: Web Link Buttons with Variable URLs
                                      John Hawkinson Level 5

                                      Sure. The answer there is the same as the answer now

                                      Just add t.remove() at the end of the loop. Of course that has to be after you use t.contents, so after you set the gotoURLBehaviors.

                                      • 16. Re: Web Link Buttons with Variable URLs
                                        a.simonds Level 1

                                        So just for clarification for anyone else, here's the workflow:

                                         

                                        1. Design layout

                                        2. Use Data Merge to import information and assign the frames the data variables

                                        3. Create button and group it with the link text frame

                                        4. Run the data merge to create the pages

                                        5. Open/run the script, which takes the now-filled-in link text frame's content and transplants it in the URL line of the buttons. The script also deletes the link text frames

                                        6. Export as an interactive PDF

                                        7. Enjoy your variable buttons!

                                         

                                        Final JS code:

                                         

                                        var b, i, p, t,
                                            doc=app.activeDocument;
                                        for (i=0; i<doc.pages.length; i++) {
                                            p = doc.pages[i];
                                            b = p.groups[0].buttons[0];
                                            t = p.groups[0].textFrames[0];
                                            b.gotoURLBehaviors.add({ url: t.contents });
                                            t.remove()
                                        }
                                        

                                         

                                         

                                        This works if you are using a single group - that of the button object and the link text frame.