Skip to main content
lfcorullon13651490
Legend
April 25, 2022
Question

[SCRIPT] Any way to check a hyperlink using specific pageItem as sourcePageItem?

  • April 25, 2022
  • 4 replies
  • 1257 views

Is there a way to point directly to the hyperlink is using a specific pageItem as sourcePageItem?

For example, when we try to add a new hyperlink to the document, and the sourcePageItem is already in use... I want to remove the hyperlink that is using it and then create the new one.

This topic has been closed for replies.

4 replies

Marc Autret
Legend
April 29, 2022

Hi @lfcorullon13651490 

 

For best performance you should probably create a pageItemId-to-hyperSourceId map (once) and cache it in your remove function. Now the way to maintain this map highly depends on the client script. If hyperlinks and/or page items are randomly created, either manually or from your main processing routine, you obviously need to update that map while addressing such and such events.

 

Anyway the basic mechanism might be implemented as follows.

 

var removeHyperSource = function(/*Document*/doc,/*PageItem*/item,  id,K,q,re,t,a,b,i,r)
//----------------------------------
// Conditionally removes the hyperlinkPageItemSource object that points out to item.
// If the link no longer exists or cannot be removed, returns false.
// => true [OK]  |  false [KO]
{
   // Checkpoint.
   // ---
   if( (!doc) || 'Document'!=doc.constructor.name ) throw "Invalid document";
   if( !(item||0).isValid || !(id=item.id) ) throw "Invalid PageItem";
   
   // HyperlinkPageItemsSources (collection.)
   // ---
   K = doc.hyperlinkPageItemSources;

   // Id-to-id map, made up once (cache.)
   // q :: { PageItemId => HyperlinkPageItemSourceId }
   // ---
   if( !(q=callee.MAP) )
   {
      re = /\d+(?=\]"\))/g;
      t = K.everyItem();
      a = t.sourcePageItem.toSource().match(re)||[]; // `<pageItemId>`[]
      b = t.id;                                      // <hypiSrcId>[]
      if( a.length != b.length ) throw "Invalid 1-to-1 correspondance.";
      q = callee.MAP = {};
      for( i=-1 ; ++i < a.length ; q[a[i]]=b[i] );
   }

   // Identify and remove the hypersource.
   // ---
   r = (t=q[id]) && (t=K.itemByID(t)).isValid;
   if( r )
   {
      try{ t.remove(); }catch(_){ r=false; }
      delete q[id];
   }

   return r;
};

// TEST
//----------------------------------
var doc = app.properties.activeDocument;
var item = app.selection[0];
var r = removeHyperSource(doc,item);
alert( r ? "OK" : "KO" );

 

Best,

Marc

Community Expert
April 25, 2022

Hi lf.corullon,

could you provide a simple test document?

Some options are already at the table…

 

You could loop the sources and retrieve the id of a given source if it is a pageItem and compare it to the one you like to use.

 

Regards,
Uwe Laubender

( ACP )

lfcorullon13651490
Legend
April 25, 2022

It's a super simple hyperlink schema.

But the document is FULL of hyperlinks.
As you can see in page 1 of this sample document, I have links to some pages.
I need to update some links (when I run the script again, for example). I have text frames and, when run for the first time, the main script creates rectangles in top of them (client request). If the client runs the script again, I used an approach very similar to Brian's suggestion to check, then loop, then remove to create again. But, since the document is really FULL of hyperlinks, each loop is taking more time than I like.

 

Thanks, Uwe!

brian_p_dts
Community Expert
Community Expert
April 25, 2022

Perhaps then the script first assigns names to the sources by their corresponding page item IDs, and then uses getByName to recall? Perhaps the bottleneck is somewhere else, ie in the rectangle creation step. 

TᴀW
Legend
April 25, 2022

myText.findHyperlinks() will give you an array of all hyperlinks that intersect with the specified text range.

 

Ariel

Visit www.id-extras.com for powerful InDesign scripts that save hours of work — automation, batch tools, and workflow boosters for serious designers.
lfcorullon13651490
Legend
April 25, 2022

It's a rectangle, not text.
I can't find any similar method for pageItems.

Thanks, Ariel.

brian_p_dts
Community Expert
Community Expert
April 25, 2022

Can't really think of a better way than this, but something like: 

 

var removeSource = function(doc, id) {
    var hlpis = doc.hyperlinkPageItemSources;
    for (var i = 0; i < hlpis.length; i++) {
        if (hlpis[i].sourcePageItem.id == id) {
            hlpis[i].remove();
            break;
        }
    }
}

var main = function() {
    var doc = app.activeDocument;
    var pi = app.selection[0];
    
    try{  
        var myHyperlinkSource = doc.hyperlinkPageItemSources.add(pi);
        myHyperlinkSource.name = "hi" + pi.id;
    }
    catch(e) {
        if (/already in use/gi.test(e)) {
            removeSource(doc, pi.id);
            var myHyperlinkSource = doc.hyperlinkPageItemSources.add(pi);
            myHyperlinkSource.name = "hi" + pi.id;
        } else {
            alert("Something is wrong with the source " + e); 
            return; 
        }
    }
}
main();

 

brian_p_dts
Community Expert
Community Expert
April 25, 2022

I guess that only gets you to the source. You could point to all hyperlinks instead, then if its source is an instanceof PageItemSource, run that ID check on the page item?