Skip to main content
Inspiring
June 8, 2023
Answered

Script function trying to link terms to text anchors isn't working as intended

  • June 8, 2023
  • 3 replies
  • 724 views

A function that is part of a larger script isn't working as intended. The purpose of the function is to identify all paragraphs on a parent page with a specified style and link each paragraphs text via a hyperlink to a previously created text anchor with a name identical to the paragraphs content. I've used the hyperlink.add() method successfully before, but the source was some user selected text and the destination was a url composed of a bit of javascript. This time, i'm having trouble getting the hyperlinkTextSource and hyperlinkTextDestination to work appropriately. the code below is the function in question with plenty of notes for each line.

    linkPopupBtn.onClick = function () {
        var glossPage;
        var textAnchors = doc.hyperlinkTextDestinations; //text anchors created in a previous, not shown, step.
        for (var i = 0; i < app.activeDocument.masterSpreads.length; i++) { //find my glossary parent page
            if (app.activeDocument.masterSpreads[i].name == "L-Glossary") {
                glossPage = app.activeDocument.masterSpreads[i].pages[0];                    
                break;
            }
        }
        var glossFrame = glossPage.textFrames[0]; //only the glossary text frame exists on this page
        app.findGrepPreferences = app.changeGrepPreferences = NothingEnum.nothing;   
        app.findGrepPreferences.appliedParagraphStyle = doc.paragraphStyleGroups.item("Glossary").paragraphStyles.item("Glossary Term Word"); //find all paragraphs with the specified paragragh style that denotes the term as opposed to defintion
        var paras = glossFrame.findGrep(); 
 
        var alertText = ""; //start a blank alert
        for (i = 0; i < paras.length; i++) { //loop through all identified paragraphs
                for (j = 0; j < textAnchors.length; j++) { //loop through all text anchors
                    var testAnchor = textAnchors[j].name + "\r"; //add a carriage return for the alert, and previously used in the comparator
                    try{ //the alert below will not trigger without the try/catch, but no error ever appears
                        if(paras[i].contents.split("\r")[0] == textAnchors[j].name) { //the identified paragraphs all end in a carriage return, remove it to compare to the anchor names
                            alertText += paras[i].contents.split("\r")[0] + ":" + testAnchor;   //this works and the alert shows all the glossary terms have matched to text anchor created in a previous, not shown, step
                            var glossPopTerm = doc.hyperlinkTextSources.add(paras[i]); //this should make the identified paragraph containing the glossary term as the hyperlink source, so you can click on it, but doesn't work
                            var glossPopDest = doc.hyperlinkTextDestinations.item(textAnchors[j]); //this should make the positive matched text anchor the destination of the glossary term above, but doesn't work
                            doc.hyperlinks.add(glossPopTerm, glossPopDest, {name:paras[i].contents.split("\r")[0]}); //this should create the actual hyperlink, but doesn't work
                            var style = doc.characterStyles.itemByName("Underline"); //find the underline character style
                            paras[i].applyCharacterStyle(style); //apply an underline to the glossary term to show the link has worked appropriately. works if the hyperlink steps above are omitted but not if they are included               
                        }
                        else {
                            alertText += para[i].contents + ":No Matches Found." //never triggers, as there should be a match for every work if previous, not shown, steps are followed appropriately
                        }
                    }
                    catch(error){} //never triigers
                    
                }
        }
        alert(alertText); //creates an alert showing all the matched pairings and unmatched terms. triggers as long as the try/catch is there or the hyperlink steps are omitted
    }

 

This topic has been closed for replies.
Correct answer Peter Kahrel

This is the problem:

 

var glossPopDest = doc.hyperlinkTextDestinations
  .item(textAnchors[j]);

 

It should be 

 

 

var glossPopDest = textAnchors[j];

 

 

Another thing: you say that the script never stops in the catch, but that's no surprise because there isn't anything there. Add a breakpoint to make the script pause at the error:

 

catch(error){
  $.bp();
}

 

then in the console you can check what the error is.

 

Finally, you did enable searching on master pages, didn't you?

3 replies

Peter KahrelCorrect answer
Community Expert
June 9, 2023

This is the problem:

 

var glossPopDest = doc.hyperlinkTextDestinations
  .item(textAnchors[j]);

 

It should be 

 

 

var glossPopDest = textAnchors[j];

 

 

Another thing: you say that the script never stops in the catch, but that's no surprise because there isn't anything there. Add a breakpoint to make the script pause at the error:

 

catch(error){
  $.bp();
}

 

then in the console you can check what the error is.

 

Finally, you did enable searching on master pages, didn't you?

Inspiring
June 9, 2023

that was it, thanks so much! i added an alert in the catch to relay the error, turns out there were some lingering half built hyperlinks in the glossary terms and some of the hyperlinks were being created with a name that already existed. i fixed both issues and it works great! thanks a ton Peter!

Community Expert
June 8, 2023

NothingEnum.nothing; should be NothingEnum.NOTHING

 

But that may not make any difference. What does make is difference is that you're adding anchors into texts that you found earlier, so the references to the found items are corrupted. You can prevent that by recasting your for-loops to go from back to front. So instead of 

 

for (i = 0; i < paras.length; i++)

 

do

 

for (i = paras.length-1; i >= 0; i--)

 

and do that for all your loops.

 

the above is not very legible

 

Unindent your code by one level; replace all tabs with two spaces; and maybe break long lines before or after dots. Makes a world of difference.

 

P.

Inspiring
June 9, 2023

Thanks for your feedback Peter, but the reverse loops didn't seem to help, it still stalls on the hyperlink methods. i've also added some extra code to count when a link has been added and when no matches were found, but neither the new code nor the orignal code work properly. heres the updated code, hopefully a bit easier to read

 

linkPopupBtn.onClick = function () {
    var glossPage;
    //text anchors created in a previous, not shown, step.
    var textAnchors = doc.hyperlinkTextDestinations; 

    //find my glossary parent page
    for (var i = 0; i < app.activeDocument.masterSpreads.length; i++) { 
        if (app.activeDocument.masterSpreads[i].name == "L-Glossary") {
            glossPage = app.activeDocument.masterSpreads[i].pages[0];                    
            break;
        }
    }

    //only the glossary text frame exists on this page
    var glossFrame = glossPage.textFrames[0]; 
    app.findGrepPreferences = app.changeGrepPreferences = NothingEnum.NOTHING;   

    //find all paragraphs with the specified paragragh style 
    //that denotes the term as opposed to defintion
    app.findGrepPreferences.appliedParagraphStyle = 
    doc.paragraphStyleGroups.item("Glossary")
       .paragraphStyles.item("Glossary Term Word"); 

    var paras = glossFrame.findGrep(); 
    var count = 0;
    var totalLinks = 0;
 
    //start a blank alert
    var alertText = ""; 
    //loop through all identified paragraphs
    for (i = paras.length -1; i >= 0; i--) { 

            //loop through all text anchors
            for (j = textAnchors.length -1; j >= 0; j--) { 
                //the alert below will not trigger without 
                //the try/catch, but no error ever appears
                try{ 

                    //the identified paragraphs all end in a carriage 
                    //return, remove it to compare to the anchor names
                    if(paras[i].contents.split("\r")[0] == 
                        textAnchors[j].name) { 
                        //count matches
                        count++;

                        //this should make the identified paragraph 
                        //containing the glossary term as the 
                        //hyperlink source, so you can click on it,
                        //but doesn't work
                        var glossPopTerm = doc.hyperlinkTextSources
                            .add(paras[i]); 

                        //this should make the positive matched text anchor 
                        //the destination of the glossary term above, 
                        //but doesn't work
                        var glossPopDest = doc.hyperlinkTextDestinations
                            .item(textAnchors[j]); 

                        //this should create the actual hyperlink, 
                        //but doesn't work
                        doc.hyperlinks.add(
                            glossPopTerm, 
                            glossPopDest, 
                            {name:paras[i].contents.split("\r")[0]}
                            ); 

                        // //Count the links that have been added
                        totalLinks++;

                        //find the underline character style
                        var style = doc.characterStyles
                            .itemByName("Underline"); 

                        //apply an underline to the glossary term 
                        //to show the link has worked appropriately.
                        //works if the hyperlink steps above are
                        //omitted but not if they are included 
                        paras[i].applyCharacterStyle(style);               
                    }
                }
                catch(error){} //never triigers

                //if no matches made, add to alerts
                if (count == 0){
                    alertText += paras[i].contents
                        .split("\r")[0] + ":No Matches Found." + "\r" 
                }
            }                
        }

    //creates an alert showing all the matched pairing and unmatched 
    //terms. triggers as long as the try/catch is there or the 
    //hyperlink steps are omitted
    alert(totalLinks + " Glossary Terms Linked" + "\r" + alertText );
}

 

 

 

Inspiring
June 8, 2023

for ease of reading im attaching the above function as a txt, as the above is not very legible