• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

Get textFrame's Tag/Label through script

New Here ,
Jun 06, 2018 Jun 06, 2018

Copy link to clipboard

Copied

Hello everyone,

I'm really sorry if this has already been asked, I have found discussions that touch on it, but haven't found any suggestions or solutions.

I am a web developer, with no inDesign experience, our graphic designer uses it to build our flyers.

We have been talking about translating the flyers to another language, and I have been working on making them interactive (with an image map)on our website.

If I'm going to suggest we revise the flyer structure for automating the translation, I'd like to also handle the image mapping (pulling image + area coordinates)

The thought was to write a js script that will pull the text frames from the file so I can work with them using other scripts to translate, get coordinates, etc.

I have more or less succeeded in doing this using the textFrame's name.
I'm currently renaming each item in the Layers window with a key-value naming structure (000-000-000|Title, 000-000-000|Description) and then splitting the name by '|' to get the product code [0] and the textFrame 'tag' [1]. Then I can run the 'tag' portion of the content through a translation script, or coordinate script as needed.

But there are dozens of pages with numerous products on each page, and multiple fields (title, description, price, quantity, product number) for each product.
I don't want to propose our designer meticulously rename thousands of elements.
I have found the Tags window to be much quicker to associate a type to each textFrame. But I haven't been able to work with the tags through script...

From what I've read, CS5 and later doesn't allow you to get a tag/label through scripting.

Is this true? Is anyone aware of any way around it?

-TLDR-

I have thousands of text (and image) elements in a InDesign file, and I would like to pull their contents out with a script and process them depending on the text field's type (product description, image, price, etc.).

Tags/Labels seem perfect, as I could just loop through all textFrame elements, and say if has tag 'description' then pass into translate(), if image getCoords().
And they are rather quick to associate with elements.

But from what I've read CS5 + doesn't allow you to work with tags through scripts in this way.

Any suggestions to accomplish this without working with the textFrame's names? (I'd like to avoid adding that much work to our graphic designer's monthly process)

If it is relevant I'm using inDesign CC 2017  V- 12.1.0.56

Thanks in advance for any input or direction you can provide. InDesign is not something I am familiar with 😕

TOPICS
Scripting

Views

7.1K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 07, 2018 Jun 07, 2018

Copy link to clipboard

Copied

Hi,

if you mean the following:

doc.pageItems.item("String")

doc.pageItems.itemByName("String")

this will work with pageItem.name only with InDesign CS5 and above.

And you get always one item in return even if more than one pageItems share the same name.

Before, in CS4, you could use the label property:

pageItem.label = "String"

and retrieve all pageItems with the same label value with:

doc.item("String");

All that said, there is one other problem you have to keep in mind:
pageItems that are nested in groups, are anchored or nested elsewhere cannot be reached with:

doc.pageItems.item("String")

doc.pageItems.itemByName("String")

If you are looking for all items, nested or not, you could use:

var nearlyAllItems = doc.allPageItems; // Returns array of pageItems

And you would loop this array to look after a distinct page item with a distinct name or label value.

Why did I named this variable nearlyAllItems and not reallyAllItems ?

Because the allPageItems array omits objects that are in states of multistate objects that are not the active state.

They cannot be reached with allPageItems!

But for this problem there is a hack! A trick I found several years ago. With every pageItems comes an id. And we could loop page items by id. That will also find page items in states that are not the active ones. Also things we never thought about as page items. What we need to do this effectively is knowing e.g. about the highest id number and possibly the lowest id number that makes sense. You could test this for yourself: Add a new document, add a simple rectangle to the page and ask about the value for id of the rectangle.

var doc = app.documents.add();

var rect = doc.rectangles.add();

alert( rect.id.toString() ); // Returns 216 in my case, your case could be different.

A good bet is that we can leave out id numbers 1 to 100, maybe 1 to 150, if we loop all page items by their ids.

And the highest number? Just add a rectangle to the document, read out its id number and remove it. Use that number to limit your loop.

Just an experiment you should do with the ESTK ( ExtendScript Toolkit ) connected to InDesign CC 2018.1 with an open document:

var doc = app.documents[0];

var tempRect = doc.rectangles.add();

var idMax = tempRect.id;

var e;

tempRect.remove();

for( var n=150; n < idMax-1 ; n++ )

{

     try

     {

          // getElements()[0] is the key feature here that will resolve a pageItem to the object that it really is:

          var currentItem = doc.pageItems.itemByID(n).getElements()[0];

          $.writeln( n +"\t"+ currentItem.constructor.name +"\t"+currentItem.name +"\t"+ currentItem.label );

     }catch( e )

     {

          $.writeln(n +"\t"+ e.message );

     };

}

Below the result of a new empty document with a different document preset than the one I did before where the highest id number was 216. This time it was 221.The loop ran from 150 to 221. If you'll test this, you could run it with 1 to the max number to see if there are interesting things you might find in the lower numbers.

Note: A page item could be addressed e.g. by its id as well:

doc.pageItems.itemByID(Number);

Important:

With getElements()[0] you can resolve that page item and know exactly what kind of pageItem this is, a rectangle, a textFrame or something else.

And with doc.pageItems.itemByID(Number) you can always drill through nested structures like groups etc.pp. to access the item.

150    ObjectStyle    [Einfacher Textrahmen]   

151    ObjectStyle    [Einfaches Raster]   

152    Object is invalid

153    CrossReferenceFormat    Vollständiger Absatz und Seitenzahl   

154    CrossReferenceFormat    Vollständiger Absatz   

155    CrossReferenceFormat    Absatztext und Seitenzahl   

156    CrossReferenceFormat    Absatztext   

157    CrossReferenceFormat    Absatznr. und Seitenzahl   

158    CrossReferenceFormat    Absatznr.   

159    CrossReferenceFormat    Name des Textankers und Seitenzahl   

160    CrossReferenceFormat    Name des Textankers   

161    CrossReferenceFormat    Seitenzahl   

162    TOCStyle    [Standard]   

163    CompositeFont    [No composite font]   

164    CompositeFontEntry    Kanji   

165    Object is invalid

166    CompositeFontEntry    Kana   

167    CompositeFontEntry    Interpunktion   

168    CompositeFontEntry    Symbole   

169    CompositeFontEntry    Latein   

170    CompositeFontEntry    Zahlen   

171    XmlStory       

172    Object is invalid

173    Object is invalid

174    Object is invalid

175    Object is invalid

176    Object is invalid

177    Object is invalid

178    Object is invalid

179    Object is invalid

180    Object is invalid

181    Object is invalid

182    Object is invalid

183    Object is invalid

184    Object is invalid

185    Object is invalid

186    Object is invalid

187    Object is invalid

188    XMLTag    Root   

189    Object is invalid

190    Object is invalid

191    Object is invalid

192    Object is invalid

193    Object is invalid

194    Object is invalid

195    Object is invalid

196    Object is invalid

197    Layer    Internal_pages_layer_name   

198    Layer    Ebene 1   

199    TrapPreset    k[No Trap Preset]   

200    TrapPreset    kDefaultTrapStyleName   

201    Spread       

202    Object is invalid

203    Object is invalid

204    Object is invalid

205    Object is invalid

206    Page    1   

207    Section       

208    MasterSpread    A-Musterseite   

209    Object is invalid

210    Object is invalid

211    Object is invalid

212    Object is invalid

213    Page    A   

214    Page    A   

215    Assignment    Nicht zugewiesener InCopy-Inhalt   

216    Object is invalid

217    Object is invalid

218    Object is invalid

219    Object is invalid

220    Object is invalid

221    Object is invalid

As you can see from this list I'm running a German InDesign version. And, it might be a surprise to you, you could also address a page with doc.pageItems.itemByID(Number). In my case, yours will be different, by id number 206. That's the page named 1. It has an empty string as label by default, but a name, and that is "1".

Please note, that in DOM documentation of all the objects listed above you will find none documented under pageItems. Only by ID you can see them as pageItems. "Normal" pageItems like rectangles, textFrames etc. pp. will be listed as well, if there are any. And this time really ALL pageItems of the document are in the list. Also the ones that are deeply nested!

Happy hunting after named or labeled items!

Regards,
Uwe

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Jun 08, 2018 Jun 08, 2018

Copy link to clipboard

Copied

Thank you so much for the detailed response.

Just to clarify, in these later versions of inDesign, there is no way to group items and then get an array/list of those group items via script?

As I mentioned, I did have it 'working' by using the items Name. But I really don't want to ask our graphics designer to carefully name 6 elements for each of the hundreds of products when she creates the flyers each month.
If that's really the best solution given the version we are using, I may have to suggest that. But if there was any way to associate a tag/label/class identifier to a group of elements so I could do something like...

//GET DESCRIPTION ITEMS

     descList = []; 

     descItems = app.activeDocument.textFrames.item("description"); 

     for ( i = 0; i < descItems.length; i ++ ) {

          descList.push(  translateText( descItems.contents )  ); 

     }

//GET PRICE ITEMS

     priceList = []; 

     priceItems = app.activeDocument.textFrames.item("price"); 

     for ( i = 0; i < priceItems .length; i ++ ) {

          priceList .push(  formatPrice( priceItems.contents )  ); 

     }

//GET IMAGE ITEMS

     imageList = []; 

     imageItems = app.activeDocument.textFrames.item("image"); 

     for ( i = 0; i < imageItems  .length; i ++ ) {

          imageList .push(  getCoordinates( imageItems )  ); 

     }

function translateText( textString ) { ... }

function formatPrice( priceString ) { ... }

function getCoordinates( imageItem ) { ... }

Again, I have little to no experience with inDesign directly beyond the past few days, but it seems like it was a very practical feature to be able to group items and retrieve a list of them. I don't see why this would have been removed in the more recent versions.

Is it a reasonable approach to consider getting a version of CS4, and trying to open the file in that just to run it through a script like this?

Thank you again,

I truly appreciate you taking the time to provide such an informative reply.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 08, 2018 Jun 08, 2018

Copy link to clipboard

Copied

aarong18402343  wrote

Thank you so much for the detailed response.

Just to clarify, in these later versions of inDesign, there is no way to group items and then get an array/list of those group items via script?

…

If you identified a group you'll get an array of all page items of a group with:

var allItemsOfGroup = group.allPageItems;

If you want to identify text frames you best resolve the items as you loop.

for( var n=0;n<allItemsOfGroup.length;n++ )

{

    var currentItem = allItemsOfGroup.getElements()[0];

    if( currentItem.constructor.name == "TextFrame" && currentItem.label == "MyLabel" )

    {

     /* do something*/

    };

};

Regards,
Uwe

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Jun 08, 2018 Jun 08, 2018

Copy link to clipboard

Copied

This sounds promising!

But how are items added to a group? Is this done with the items name through scripting as well?

I also wanted to ask about names vs tags regarding tables. Our flyers currently have lists of products just in a text box.

          000-000-000     title     quantity     price

          000-000-000     title     quantity     price

          000-000-000     title     quantity     price

I was going to suggest we use tables,

1. So I can distinguish between rows for the image map, to link to different products

2. So I can distinguish between the columns, to know what to translate (text) and what to format (currency)

3. So it's hopefully slightly easier for our designer to adjust styling and column widths, etc. if needed

But to further tease me with how convenient tags/labels would be for me in this specific instance, it looked like the name is attached to the table, so rows and columns can't have their own names, but they can be given different tags.

Is that correct?

Sorry for all the newbie questions. You have been incredibly helpful.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 08, 2018 Jun 08, 2018

Copy link to clipboard

Copied

Cells and tables can be labeled. Property label, value String.

Property name isn't worth a try, because it's not unique and tied to a cell's position in the grid of rows and columns.

Boy, you'll have a steep lerning curve especially with InDesign tables.

Regards,
Uwe

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Jun 08, 2018 Jun 08, 2018

Copy link to clipboard

Copied

Laubender  wrote

Boy, you'll have a steep lerning curve especially with InDesign tables.

I am starting to realize this 😕

I'm installing our previous CS4 version right now to see if it's easy enough to just open the file to run the script.
But if not it sounds like my best bet will be to have a conversation about using a more deliberate naming structure for the elements we are looking to map or translate.

Thanks again for all the help.

You have probably saved me hours of additional research and trial.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 08, 2018 Jun 08, 2018

Copy link to clipboard

Copied

I hope you already realized this:

There is DOM documentation available by Jongware for InDesign CS to CS6.

Indesign JavaScript Help

Especiall look into the chm files for excellent searchability.

For the latest available InDesign DOM documentation which is for CC 2018 ( not CC 2018.1) look here:

https://www.indesignjs.de/extendscriptAPI/indesign-latest/#about.html

Best,
Uwe

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 09, 2018 Jun 09, 2018

Copy link to clipboard

Copied

https://forums.adobe.com/people/Guild+-+Office+Pro  wrote

…

I'm installing our previous CS4 version right now to see if it's easy enough to just open the file to run the script. …

If the script in not meant to run with CS4 that's no good idea. The designers will hate you if they are forced to work with CS4 when they are currently on CC 2017.1. Better concentrate on version CC 2017.1.

Regards,
Uwe

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Jun 11, 2018 Jun 11, 2018

Copy link to clipboard

Copied

I managed to get and update the element's contents pulled via XML tags using xpaths in our current InDesign version

//GET LIST OF 'Title' ELEMENTS

     var doc = app.activeDocument;

     var xmlTag = doc.xmlElements[0];

     var titleTag = xmlTag.evaluateXPathExpression("//Title")

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

     {

          //GET CONTENTS

               alert('content ' + i + ': ' + titleTag.xmlContent.contents);

          //UPDATE CONTENTS

               titleTag.contents = "Translation of : " + titleTag.contents;

     }

But I want to pull the translated text (and alternate pricing, etc.) from a spreadsheet. Ideally using the product number as an identifier.

Ex:

Code               EnglishTitle          FrenchTitle       PriceLvl1         PriceLvl2

000-000           itemA                   itemÀ               1.99               2.99

I thought the most logical approach would be to use the product code as the element's name.

However, every attempt I've made to get the name using the XML object has returned blank values or given errors.

//GET LIST OF 'Title' ELEMENTS

     var doc = app.activeDocument;

     var xmlTag = doc.xmlElements[0];

     var titleTag = xmlTag.evaluateXPathExpression("//Title")

  

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

     {

          //GET CONTENTS

             alert('content ' + i + ' : ' + titleTag.xmlContent.contents);

          //GET NAME

             alert('name ' + i + ' : ' + titleTag.xmlContent.name);  //BLANK

             alert('name ' + i + ' : ' + titleTag.name);  //ERROR (Object does not support the property or method 'name')

     }

My current 'quick fix' workaround for this is to check all the textframe elements to find contents that match the XML object, then I can get that textFrame's name to work with.

//GET LIST OF 'Title' ELEMENTS

     var doc = app.activeDocument;

     var xmlTag = doc.xmlElements[0];

     var titleTag = xmlTag.evaluateXPathExpression("//Title")

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

     {

           //GET CONTENTS

                alert('content ' + i + ': ' + titleTag.xmlContent.contents);

          //FIND TEXTFRAME MATCH

               for (var j=0; j<app.activeDocument.textFrames.length; j++)

               {           

                    if(app.activeDocument.textFrames.contents == titleTag.contents)

                    {

                         alert("Found Match - " + app.activeDocument.textFrames.name);

                         app.activeDocument.textFrames.contents = "Translation of : " + app.activeDocument.textFrames.name ;

                     }

                }

        }

This allows me to get the textframe name, but it is clearly not an efficient approach, as it has to loop through all textframes for each XML tag I modify. And if anything shares the same contents (which is entirely possible with prices) it could confuse the two elements.

Is there a way to get the textframe's name attribute (if that's the correct terminology for inDesign) from the associated XML element?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 12, 2018 Jun 12, 2018

Copy link to clipboard

Copied

Hi,

don't know if this is the case with your sample, but XML explicitly disallows numbers as the first character of an element name.

Regards,
Uwe

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Jun 13, 2018 Jun 13, 2018

Copy link to clipboard

Copied

LATEST

Oh, yes I have been putting all my element names in tag brackets/guillemets to avoid this issue.

Ex: <000-223>

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Jun 07, 2018 Jun 07, 2018

Copy link to clipboard

Copied

Hi,

You might want to investigate insert/extract label. Labels are very flexible in that just about any text can be inserted into and extracted from a label. insertLabel uses a name/value pair. extractLabel requires the name to get the text stored. You can even insert a complete script (written as plain text) and run the inserted script using doScript.

For example:

var myScript = "alert ('Hello')";

var selRef = app.selection[0];

selRef.insertLabel("script", myScript);

//later as part of another script, extract and run the inserted script

var aScript = selRef.extractLabel("script");

app.doScript(aScript);

Just a thought.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 08, 2018 Jun 08, 2018

Copy link to clipboard

Copied

Hi,

the main problem of our OP will stay. How to efficiently label or name the items.

If there is a scheme for this one could write a script that does exactly this without involving the user very much.

On the other hand there are translation software suits that are using memory systems for phrases and other standard expressions that are working with IDML. Maybe that's the best way to go regarding translations.

Best,
Uwe

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Jun 08, 2018 Jun 08, 2018

Copy link to clipboard

Copied

I have done a little research into translation software. But other people in the company have worked out the translations already, so I thought simply pulling the data, swapping it and plugging it back in would be the easiest approach on my end.

If there are some suits/plugins/scripts that would translate directly from the file that might still be worth considering. Our French clients have been a little 'particular' about the translation in the past (Quebec French / France French) so I know some of our board doesn't want to rely fully on automated translations. But still something I may look into more.

I was really hoping I would also be able to address the image mapping that I mentioned in my first post.

I originally put together / came across a script to pull image coordinates. But it did all graphics.

I was hoping if our designer was able to tag items, I could use those identifiers to determine what I want to get the coordinates of, and use for the image map. That way customers could click on the images or text to view a product.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Jun 08, 2018 Jun 08, 2018

Copy link to clipboard

Copied

Thanks for the response.

If I'm following the suggestion correctly; it would still require me to address each item by name through scripting.

I'm trying to avoid using the name, as there are just so many to work with. And I think a much higher mistake of typos and human error.

I did come across some info on adding labels to items through scripting in CS5+, but I don't think really it addresses my issue.

I appreciate the suggestion though.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines