WORKING WITH TABS

When looking for samples of code don’t overlook the scripts provided by Adobe in the InDesign’s Scripts. Recently I had occasion to look at their TabUtilities script when working on one that involved tabs. The TabUtilities script includes a number of examples for creating a tab stop using properties for position, alignment, and leader.

Additionally, this script has a good example of creating a custom dialog with a rqdiobutton group. As a bonus, there is code for calculating horizontal positions on a page using the position of an insertion point, and properties of a text frame’s text frame preferences. Text frame preference provides inset spacing values and text column fixed widths which can be used to calculate horizontal coordinates. The code is fairly involved so we will let you explore this script on your own.

For the purpose of this post we will concntrate on creating tabs and using tab positions for creating items such as guides and image containers.

CREATING A TAB

Creating a tab for a paragraph can be condensed into the following:

Fixed Position Tab

set tabPosition to 1
set tabLeader to ""
tell application "Adobe InDesign CC 2019"
   set measurement unit of script preferences to inches
   set tabAlignment to left align
   set myTextObjects to ¬
{insertion point, character, word, line, text style range, paragraph, text column, text, story, text frame}
   set mySelection to object reference of selection
   if (count mySelection) > 0 then
     if class of item 1 of selection is in myTextObjects then
	set myClass to class of item 1 of mySelection
	set myParagraphs to object reference of paragraphs of item 1 of mySelection
	set myParagraph to object reference of item 1 of myParagraphs
	tell myParagraph
	   make tab stop with properties {alignment:tabAlignment, position:tabPosition, leader:tabLeader}
	end tell
      end if
   end if
end tell

For all of the paragraphs in a text frame, add a repeat loop to the above that iterates through the paragraph references returned to the variable myParagraphs.

TABS FOR PARAGRAPH STYLES

If the paragraphs in a text frame or story have been assigned a paragraph style, its tab list property can be set to a list of tab records. Each tab record in the list can define the position, the alignment, and leader foor the tab. Following is an example of setting a tab for a paragraphs style. The tab in this example has a leadered right-aligned tab at the right edge of the text frame. This is often used to style text for tables of contents and event programs.

Right Aligned Tab

(*Expects a text frame selection with paragraphs assigned to a paragraph style*)
set tabLeader to ". "
tell application "Adobe InDesign CC 2019"
   set measurement unit of script preferences to points
   set mySelection to selection
   if mySelection is not {} and class of item 1 of mySelection is text frame then
	set frameRef to item 1 of mySelection
	copy geometric bounds of frameRef to {y0, x0, y1, x1}
	set frameRight to (x1 - x0)
	set paraStyle to applied paragraph style of paragraph 1 of frameRef
	set tab list of paraStyle to {{position:frameRight}}
   end if
end tell

TAB POSITIONS

Should you wish to set tabs for a spanned headline so that tabbed text aligns to text frame columns this can be easily handled with the following:

Spanned Head

tell application "Adobe InDesign CC 2019"
   set tabAlign to left align
   set tabLeader to ""
   set sideRef to 1 --for right align set sideRef to 2
   set measurement unit of script preferences to points
   set selList to selection
   if selList is not {} and class of item 1 of selList is text frame then
	set frameRef to item 1 of selection
	tell text frame preferences of frameRef
	   copy {text column fixed width, text column count, text column gutter} to ¬
{colWidths, numCol, colGut}
	end tell
	if numCol > 1 then
	   set colList to my calcColumns(colWidths, numCol, colGut)
	end if
	set myPara to a reference to paragraph 1 of frameRef
	set myTabList to {}
	repeat with i from 2 to numCol
	   set end of myTabList to ¬
{alignment:tabAlign, leader:tabLeader, position:item sideRef of item i of colList}
	end repeat
	if name of applied paragraph style of myPara is not "[Basic Paragraph]" then
	   set myObject to applied paragraph style of myPara
	else
	   set myObject to myPara
        end if
        tell myObject
	   set span column type to span columns
	   set tab list to myTabList
        end tell
   else
	display dialog ("Requires a selected text frame")
   end if
end tell
(*Returns left and right edge positions for columns in text frame*)
on calcColumns(colWidths, numCol, colGut)
   set colList to {}
   set x0 to 0
   repeat with i from 1 to numCol
      set x1 to x0 + colWidths
      copy {x0, x1} to end of colList
      set x0 to x1 + colGut
   end repeat
   return colList
end calcColumns

…Before running script

…After running script

Notice that instead of creating tab stops individually, a paragraph reference can take advantage of the tab list property. Also, be aware that tab positions are relative to the left edge of the text frame. The calcColumns handler can also be used for placing text frames over the columns but the horizontal coordinates (x0, x1) would need to take into consideration the horizontal position of the subject text frame within the page. An example of this is shown in the following example.

EXISTING TABS

Should you have a tabbed headline as was created above you might wish to create threaded text frames that align to the heads. This would be a best case scenario when your text columns are different widths.

Create Frames to Tabs

(*Expects paragraph in header text frame to be selected*)
set gutWid to 12 --gutter width in points
set rectHgt to 200 --image container height in points
tell application "Adobe InDesign CC 2019"
   set measurement unit of script preferences to points
   set selList to selection
   if selList is not {} and class of item 1 of selList is text then
      set myRef to a reference to item 1 of selection
      set myTabs to tab list of myRef
      set frameRef to item 1 of parent text frames of myRef
      set x0 to item 2 of geometric bounds of frameRef
      set pageRef to parent page of frameRef
      set colList to {}
      repeat with i from length of myTabs to 1 by -1
	 set colPos to (position of item i of myTabs) + x0
	 set end of colList to colPos
      end repeat
      my createLinkedFrames(frameRef, colList, rectHgt, gutWid)
   end if
end tell
(*Creates linked text frames based on tab positions in selected headline*)
on createLinkedFrames(frameRef, colList, rectHgt, gutWid)
   tell application "Adobe InDesign CC 2019"
      set pageRef to parent page of frameRef
      copy geometric bounds of frameRef to {y0, x0, y1, x1}
      tell pageRef
	 repeat with i from 1 to length of colList
	    set colPos to item i of colList
	    set thisBounds to {y1, colPos, y1 + rectHgt, x1}
	    set thisFrame to make text frame with properties {geometric bounds:thisBounds}
	    if i > 1 then
		set next text frame of thisFrame to lastFrame
	    end if
	    set x1 to colPos - gutWid
	    set lastFrame to thisFrame
	 end repeat
	 set thisFrame to make text frame with properties {geometric bounds:{y1, x0, y1 + rectHgt, x1}}
	 set next text frame of thisFrame to lastFrame
      end tell
   end tell
end createLinkedFrames 

…After creating linked text frames

ONWARD AND UPWARD

Now that you have lots of code to work with, all you need is to add some error handling along with custom dialogs to allow users to define the values required for the scripts. And, don’t forget to spend some time with the TabUtilities script.

Disclaimer:
Scripts provided are for demonstration and educational purposes. No representation is made as to their accuracy or completeness. Readers are advised to use the code at their own risk.