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

How to: Place anchoredObject after found text?

Community Beginner ,
Dec 30, 2022 Dec 30, 2022

Copy link to clipboard

Copied

I am new to inDesign scripting. I’ve been poring over the discussion boards and help docs and cannot find anything that will help me even get near the answer. Thanks in advance, getting my head around these concepts (and the lack of examples in online resources) have me pulling my hair out. 

 

I’m working in Visual Studio Code and writing in JavaScript.

 

I have a Story consisting of headers and related paragraphs. Like flowers and descriptions. (See below.) I also have an array with the flower names and the related imagenames in a folder on my drive.

 

Generally speaking, how can I…

  • Search for the text in the headers 
  • Insert the related image between the header and the paragraphs as an anchored object?

 

Screen Shot 2022-12-30 at 12.45.00 AM.png Screen Shot 2022-12-30 at 12.51.15 AM.png

 

I can find the text using findText(), but the insertion point it gives is at the beginning of the text, not the end, and not inclusive of the /r paragraph marker.

 

How can I say “Yes this insertionPoint, but [headertext.length]+1 later”? Then “add this rect AND a /r character”?

 

I have managed to add a rect as an anchored object to the (wrong) insertionPoint, and even load, place, and fit the image. That might be OK, if I could figure out how to then move the rect, but I cannot.

 

How can I say “Take this [anchoredObject rect] and move it [headertext.length]+1 later in the story?”

 

I can’t imagine that the code will help, because it’s not working, and what I’m looking for is an explanation of how things are supposed to work, generally, but here it is…

 

 

 

    var this_flower_name = this_card_data[0];
    var this_flower_image = this_card_data[1];
    var this_file = File(this_flower_image);

    // find the flower name in the text
    app.findTextPreferences = app.changeTextPreferences = NothingEnum.NOTHING;
    app.findTextPreferences.findWhat = this_flower_name;
    var finds = flower_parent_story.findText();
    if (finds.length == 0) {
        alert('flower title not found?!');
        throw new Error();
    } else {
        var this_insertionPoint = finds[0].insertionPoints[0];
        var image_container = this_insertionPoint.rectangles.add({geometricBounds:[0,0,1.5,1], contentType:ContentType.GRAPHIC_TYPE});
        this_insertionPoint.contents = "\r";
        var flower_image_container_style = doc.objectStyles.item("flower_container");
        image_container.applyObjectStyle(card_style);

        var myGraphic = image_container.place(this_file);
        image_container.fit(FitOptions.PROPORTIONALLY);
        image_container.fit(FitOptions.FRAME_TO_CONTENT);
    }

 

TOPICS
How to , Scripting

Views

242

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

correct answers 1 Correct answer

Community Expert , Dec 30, 2022 Dec 30, 2022

Include the return mark in your find text: app.findTextPreferences.findWhat = this_flower_name + "\r"

 

Then get the last insertion point of the find: finds[0].insertionPoints[-1]

 

On mobile, but hopefully that steers you on the right path. 

 

Votes

Translate

Translate
Community Expert ,
Dec 30, 2022 Dec 30, 2022

Copy link to clipboard

Copied

Include the return mark in your find text: app.findTextPreferences.findWhat = this_flower_name + "\r"

 

Then get the last insertion point of the find: finds[0].insertionPoints[-1]

 

On mobile, but hopefully that steers you on the right path. 

 

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 ,
Dec 31, 2022 Dec 31, 2022

Copy link to clipboard

Copied

So much simpler than I imagined. That helped me understand how to set it in the right place. I don’t need to move the container now, but so I know, any leads on how to do that, i.e. Move anchoredObjects from one place to another in the Story? And thank you!

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 ,
Dec 31, 2022 Dec 31, 2022

Copy link to clipboard

Copied

And/or how to search for that anchoredObject later? Can they be named?

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 ,
Jan 01, 2023 Jan 01, 2023

Copy link to clipboard

Copied

A "level up" moment for me in my scripting journey was realizing the relationship between myDocument.pageItems and myDocument.allPageItems. The first gives you all the page items at the top level of the document object, meaning the text frames of your stories, standalone graphic containers, lines, top-level groups, etc. Note that this does not include any anchored objects. 

 

myDocument.allPageItems gives you everything, including anchored objects. It's also an array, as opposed to a "collection". Collections are very important when it comes to scripting; they allow you to operate on everything at the same time with, say, myDocument.pageItems.everyItem(). 

 

Taking it a step further, you'll notice in the documentation for, say, a Story or TextFrame object, that they contain collections. So, myDocument.stories[0].rectangles gives you every embedded rectangle in the first story that the script finds. You can take that step further by getting a bit wild with everyItem() and getElements(), by finding all anchored objects in all stories in a document with: myDocument.stories.everyItem().rectangles.everyItem().getElements(); 

 

Marc Autret does a great breakdown of everyItem() here: https://www.indiscripts.com/post/2010/06/on-everyitem-part-1

 

To answer your second question, yes you could name your anchored objects then recall them later. Say, as you were embedding them, you named them as 

 

image_container.name = "anch" + i;

 

You could then recall an individual anchor with myDocument.rectangles.itemByName("anch1"); which would be the same as myDocument.stories.everyItem.rectangles.itemByName("anch1"); assuming that the name is unique (by using the i iterator on the find across the whole doc). 

 

Then you can move objects with myRect.move(LocationOptions.AFTER, someInsertionPointObject)

 

Not sure this is the clearest explanation, as it's early and I have *not* had a lot of coffee, but hopefully that gives you some ideas. Definitely play with everyItem() and getElements(); everyItem is still a collection, whereas once you use getElements(), you essentially convert that collection into an array and then can iterate through the array. Take care of @Laubender's points about insertionPoint indexes changing when you move things around. 

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 ,
Jan 01, 2023 Jan 01, 2023

Copy link to clipboard

Copied

Also will note that if (pageItem.anchoredObjectSettings && pageItem.parent instanceof Character) , then the item is anchored. 

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 ,
Dec 30, 2022 Dec 30, 2022

Copy link to clipboard

Copied

Hi @Chris Noessel_731, you are doing very well for your first script! I had a quick play with your code and tweaked a few small things. Not much—you were pretty close! See what you think.

It might be fine to put the anchored graphic in the first insertion point of the heading. Just set the object style to put it where you want. See my attached indesign sample file for an example object style "flower-container". The object style sets width and height, and anchored object options.

- Mark

 

// this just for me to test
var this_card_data = [
    'Abutilon',
    '~/Desktop/abutilon.png'
]

function main() {

    var this_flower_name = this_card_data[0];
    var this_flower_file = File(this_card_data[1]);

    var doc = app.activeDocument;

    // find the flower name in the text
    app.findTextPreferences = app.changeTextPreferences = NothingEnum.NOTHING;
    app.findTextPreferences.findWhat = this_flower_name + '\r';
    var finds = doc.findText();

    if (finds.length == 0) {
        alert('flower title not found?!');
        return;
    }

    else {
        var this_insertionPoint = finds[0].insertionPoints[0];
        var image_container = this_insertionPoint.rectangles.add({ contentType: ContentType.GRAPHIC_TYPE });
        image_container.applyObjectStyle(doc.objectStyles.item("flower_container"));
        var myGraphic = image_container.place(this_flower_file);
        image_container.fit(FitOptions.PROPORTIONALLY);
        image_container.fit(FitOptions.FRAME_TO_CONTENT);
    }


} // end main

app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Place flower photos');

 

Screenshot-2022-12-30-at-21.32.41.gif

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 ,
Dec 31, 2022 Dec 31, 2022

Copy link to clipboard

Copied

Hi @Chris Noessel_731 ,

be aware that if you insert characters, also an added rectangle counts as character, that the positions of the next insertion point in the same story would move. Also do another check on the found text instances for the applied paragraph style in case that the find strings are found more than one time.

 

Regards,
Uwe Laubender
( Adobe Community Expert )

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 ,
Jan 02, 2023 Jan 02, 2023

Copy link to clipboard

Copied

LATEST

Just adding one thing:

Also a character has a move() method. Or a duplicate() method.

See the details in the DOM documentation:

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

 

Note that the second argument of the method can be Text.

And an insertionPoint is also part of Text.

So you could move a character to a position after or before an insertionPoint.

Experiment with that. Select one character and move it inside the same story or to another one.

 

// One single character selected, could be also the anchor of an anchored rectangle.
// Move it to the end of the parent which usually is the story

var myCharacter = app.selection[0];
myCharacter.move( LocationOptions.AT_END , myCharacter.parent );

 

// Anchored object selected!

var myCharacter = app.selection[0].parent;
myCharacter.move( LocationOptions.AT_END , myCharacter.parent );

 

// Anchored object selected.
// Move it to the SECOND paragraph of the SAME story:

var myCharacter = app.selection[0].parent;
myCharacter.move( LocationOptions.AT_BEGINNING , myCharacter.parent.paragraphs[1] );

 

If your traget is the next paragraph in the same story it will get a bit more complicated.

 

You could get the paragraph the character is positioned in by myCharacter.paragraphs[0], but you cannot widen the scope what a character can see around it with e.g. myCharacter.paragraphs[1]. You need to work with property index of a character or an insertion point to "calculate" the position of the next paragraph in the story.

 

Do the following with a selected character a bit downstream of your text.

A character in the third or fourth paragraph of your text perhaps. Note the result:

var myCharacter = app.selection[0];
myCharacter.paragraphs[0].characters[-1].insertionPoints[1].index;

 

Then select a character in the next paragraph and do:

var myCharacter = app.selection[0];
myCharacter.paragraphs[0].index;

 

Do you see a relationship between the results of the two last script snippets?

 

Then do the following with a selected character where another paragraph is following the paragraph the character is in:

var myCharacter = app.selection[0];

app.select
(
	myCharacter.parent.characters
	[
		myCharacter.paragraphs[0].characters[-1].insertionPoints[1].index
	]
);

 

What is the result of that?

Which character is now selected?

 

If you have done that, step back…

Before thinking about index too much do the following:

 

Loop all characters of a little story with several paragraphs.

Read out the results for characters[n].index. For every single character.

Do the same with all insertionPoints of the story.

Also the same with all paragraphs of the story.

 

Come back to the little script snippets above and think again about the values of index.

 

Note:

paragraphs[0] is the first paragraph of a given scope. In our case the paragraph of a selected character.

characters[-1] is the last character of a given scope. In our case the last character of the paragraph of the selected character. Every character has two insertion points. The first one before the character, the second one behind it.

 

Regards,
Uwe Laubender
( Adobe Community Expert )

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