Skip to main content
Bedazzled532
Inspiring
May 10, 2023
Answered

Split and anchor textframes using script

  • May 10, 2023
  • 1 reply
  • 3569 views

Hi there

I am working on a long document where I have a threaded textframe.
I have shown an example using gray textframe in the screenshot.

I have another text frame denoted by yellow textframe in the screenshot
where I have some text which will be anchored in the gray textframe.
I have named it as "source" in layers.


I have written a script through which I am splitting each line in
yellow textframe to a textframe of their own. Meaning 3 textframes will be created out of yellow textframe.

 

var doc = app.documents[0];

//var myFrame = doc.textFrames[0];

var myParas = doc.stories.everyItem().paragraphs.everyItem().getElements(); 


var noParas = myParas.length;
alert(noParas);

for(i=0;i<noParas;i++){
	
var textFrame = doc.textFrames.add();	

	textFrame.properties = 
	{
			geometricBounds :[0,0,50,50],
			strokewidth: 0,
			fillColor : "None",
			name : "test"+(i+1).toString(),
			contents : myParas[i].contents
	};
}

 


The issues which I am facing:

1.The script is creating textframes for gray text box also. I want textframes for contents in yellow textframes only.
2.The textframes which will be created should have object style of its own. Obj Style name will be rukus".
3.The created textframes should be anchored just after or before the "*" mark in the gray textframe.

 

First part is somewhat working through the script which I have written but I am not able to do other parts as I am still learning scripting. 
Any suggestion would be helpful.

Thanks

 

This topic has been closed for replies.
Correct answer nicosh

I'm not JS expert so can't give an example code - but you can't - or at least shouldn't - use "external" search methods on the text contents of InDesign's text objects - you need to use built in "plain" and grep find methods.

Otherwise you'll end up with unexpected results - for example, if uou try to use JS's RegExp method - "\s" (any white space) will remove index markers, etc. - but if you use built in grep methods - InDesign will ignore those.

 

That's why I was suggesting using built in find functionality - rather than iterating through all paragraphs. 

 

But like I've said - I'm not JS guy so won't give you a specific code examples - but there is plenty on this forum or on Google. 

 


Hi @Bedazzled532 , a third way to search following the @Robert at ID-Tasker suggestion.

This way is using findGrep method:

1. Add a new variable with the unicode character in string format. Used for findWhat property in findGrepPreferences.

var unicodeTxt = '\\x{002A}';

2. New function with findGrep method. This function returns a multidimensional array with the paragraphs and the index of the unicode character.

function findUnicodeGrep(txtFrame) {
  app.findGrepPreferences = app.changeGrepPreferences = null;
  app.findGrepPreferences.findWhat = unicodeTxt;
  var myFound = txtFrame.findGrep();
  var tp = [];
  for (var i = 0; i < myFound.length; i++) {
    var temp = [];
    //object paragraph
    var p = myFound[i].paragraphs.item(0);
    //content of the paragraph
    var t = p.contents;
    //unicode character index in the paragraph
    var result = unicode.exec(t);
    temp[0] = p;
    temp[1] = result.index;
    tp.push(temp);
  }
  return tp;
}

The full script (you can delete the unused functions):

I'm pretty sure that this script can be improve but I think that it does its job.

//get handle to document
var doc = app.documents[0];
// var character = '*';
// unicode value for '*' character
var unicode = /\u002A/;
//unicode string format
var unicodeTxt = '\\x{002A}';

//get handle to textFrames
var txtFrame = doc.textFrames;

//get handle to paragraphs
var des = txtFrame.itemByName('destination');

//get paragraphs with character '*' and its position
// myResults = findCharacter(character, des);

//get paragraphs with unicode character and its position
// myResults = findUnicode(unicode, des);

//get paragraphs with unicode character and its position via findGrep() method
myResults = findUnicodeGrep(des);

//loop through paragraphs with character '*'
for (var i = myResults.length - 1; i >= 0; i--) {
  //insertion point
  var point = myResults[i][0].insertionPoints.item(myResults[i][1]);
  // add frame at insertion point
  try {
    tf = point.textFrames.add();
    tf.properties = 
    {
      geometricBounds :[0,0,10,30],
      strokewidth: 0,
      fillColor : "None",
      name : "test"+(i+1).toString(),
      contents : txtFrame.itemByName('source').paragraphs[i].contents,
      appliedObjectStyle: doc.objectStyles.item("rukus")
    };
    tf.anchoredObjectSettings.properties = {
      anchoredPosition: AnchorPosition.ANCHORED,
      anchorPoint : AnchorPoint.TOP_RIGHT_ANCHOR,
      verticalReferencePoint : VerticallyRelativeTo.LINE_XHEIGHT
    }; 
  } catch (error) { }
}


txtFrame.itemByName('source').remove();

// search for character '*' in a text frame
// return a multidimensional array with the paragraph and the '*' position
// index[0], paragraph
// index[1], position
function findCharacter(character, txtFrame) {
  var p = txtFrame.paragraphs;
  var tp = [];
  for (var i = 0; i < p.length; i++) {
    var result = p[i].contents.indexOf(character);
    var temp = [];
    if (result != -1) {
      temp[0] = p[i];
      temp[1] = result;
      tp.push(temp);
    }
  }
  return tp;
}

// search for unicode character in a text frame
// return a multidimensional array with the paragraph and the unicode position
// index[0], paragraph
// index[1], position
function findUnicode(unicode, txtFrame) {
  var p = txtFrame.paragraphs;
  var tp = [];
  for (var i = 0; i < p.length; i++) {
    var temp = [];
    var result = unicode.exec(p[i].contents);
    if (result !== null) {
      temp[0] = p[i];
      temp[1] = result.index;
      tp.push(temp);
    }    
  }
  return tp;
}

// search for unicode character in given frame
// return a multidimensional array with the paragraph and the unicode character position
// index[0], paragraph
// index[1], position
function findUnicodeGrep(txtFrame) {
  app.findGrepPreferences = app.changeGrepPreferences = null;
  app.findGrepPreferences.findWhat = unicodeTxt;
  var myFound = txtFrame.findGrep();
  var tp = [];
  for (var i = 0; i < myFound.length; i++) {
    var temp = [];
    //object paragraph
    var p = myFound[i].paragraphs.item(0);
    //content of the paragraph
    var t = p.contents;
    //unicode character index in the paragraph
    var result = unicode.exec(t);
    temp[0] = p;
    temp[1] = result.index;
    tp.push(temp);
  }
  return tp;
}

 

1 reply

Robert at ID-Tasker
Legend
May 10, 2023

1) you are collecting paragraphs from all stories - including the grey TF - you need to change your approach and work on two Stories - source (yellow) and destination (gray) ,

 

2) you need to apply ObjectStyle,

 

3) back to 1) - you need to go through a destination story - look for "*" and then insert Paragraphs from the source story.

 

I'm not JS guy so can't give you code. 

 

Bedazzled532
Inspiring
May 10, 2023

@Robert at ID-Tasker Thanks for the reply.

 

I have modified the code. Took help from internet. Here is how the code looks now.

 

It creates only 3 textframes as per the source textframe and applies "rukus" object style to it. I am not able to carry out the 3rd part.

 

//get handle to document
var doc = app.documents[0];

//get handle to textFrames
var txtFrame = doc.textFrames;

for(var i = 0 ; i < txtFrame.length; i++)
{
    if(txtFrame[i].name == "source")
	{
		myParagraphs = txtFrame[i].paragraphs.everyItem().getElements();
		noParagraphs = myParagraphs.length;
		alert(noParagraphs);
		
		for(j=0;j<noParagraphs;j++)
		{		
			var textFrame = doc.textFrames.add();	

			textFrame.properties = 
			{
				geometricBounds :[0,0,50,50],
				strokewidth: 0,
				fillColor : "None",
				name : "test"+(j+1).toString(),
				contents : myParagraphs[j].contents
			};
			textFrame.applyObjectStyle(doc.objectStyles.item("rukus"));
		}
	break;
	}
}

 

 

Inspiring
May 11, 2023

Hi @Bedazzled532 

As @Robert at ID-Tasker said you have to work with the two frames. I have named the gray text frame as 'destination' but you can refer it as you want (txtFrame.name != 'source').

Try this:

//get handle to document
var doc = app.documents[0];

//get handle to textFrames
var txtFrame = doc.textFrames;

//get handle to paragraphs
var des = txtFrame.itemByName('destination');
var desPar= des.paragraphs;

for (var i = desPar.length - 1; i >= 0; i--) {
  //search for position 
  var pos = desPar[i].contents.indexOf('*') + 1;
  //insertion point
  var point = desPar[i].insertionPoints.item(pos);
  // add frame at insertion point
  tf = point.textFrames.add();
  tf.properties = 
  {
    geometricBounds :[0,0,10,30],
    strokewidth: 0,
    fillColor : "None",
    name : "test"+(i+1).toString(),
    contents : txtFrame.itemByName('source').paragraphs[i].contents,
    appliedObjectStyle: doc.objectStyles.item("rukus"),
  };
  tf.anchoredObjectSettings.properties = {
    anchoredPosition: AnchorPosition.ANCHORED,
    anchorPoint : AnchorPoint.TOP_RIGHT_ANCHOR,
    verticalReferencePoint : VerticallyRelativeTo.LINE_XHEIGHT
  }; 
}

 

I assume that number or paragraphs in both text frames are the same, if not you will need additional scripting to check and avoid errors.