Automating Adobe InDesign 2017


InDesign Script Handlers (Functions)

Thursday, September 28, 2017

InDesign Script Handlers (Functions)

Our previous blog introduced a number of handlers (functions) that you might want to keep handy in a library for use in other scripts. These handlers were:

  • make layer - creates a named layer if one does not already exist. In either event, the reference to the layer is returned.
  • makeRectangle - creates a rectangle using the reference to a parent object passed to the handler. Names the rectangl, sets its geometric bounds,fill color, fill tint, stroke weight, strokecolor, stroke tint, and parent layer.
  • makeTitleBox - creates a no-fill, no-stroke text frame with a title on a given layer using the text for the label and an assigned paragraph style.

Function: makeTextFrame

Similar to the makeTitleBox, you might want a handler that allows setting values for parameters such as fill color, tint, stroke weight, and fit. The beginnings for a suggested script follows.

Make Frame - AppleScript

set layerRef to missing value
set gBounds to {100, 30, 150, 500}
set textContent to "This is a test, only a test"
set fitToContent to false
set pStylename to "Heading1"
set fillColor to "Black"
set fillTint to 30
set strokeWeight to 2
set strokeColor to "Black"
set strokeTint to 100
set frameName to "Test Frame"
tell application "Adobe InDesign CC 2017"
  set measurement unit of script preferences to points
  set docRef to document 1
  set vJust to center align
  set pStyle to paragraph style pStylename of docRef
  set pageRef to active page of active window
  set textFrame to my makeTextFrame(pageRef, frameName, ¬
gBounds, fillColor, fillTint, strokeWeight, strokeColor, strokeTint, pStyle, ¬
textContent, fitToContent, vJust, layerRef)
end tell

(*Expects actual text to be passed to text frame created. layerRef can be 
missing value, and itemName can be empty string ""*)
on makeTextFrame(parentRef, itemName, gBounds, fillColor, fillTint, strokeWeight,¬
 strokeColor, strokeTint, pStyle, textContent, fitToContent, vJust, layerRef)
  tell application "Adobe InDesign CC 2017"
    tell parentRef
      set myFrame to make text frame with properties {geometric bounds:gBounds,¬
 fill color:fillColor, fill tint:fillTint, stroke weight:strokeWeight}
      if strokeWeight is not 0 then
	 set stroke color of myFrame to strokeColor
	 set stroke tint of myFrame to strokeTint
      end if
      if itemName is not "" then
	 set name of myFrame to itemName
      end if
      set contents of insertion point 1 of myFrame to textContent
      tell text 1 of parent story of myFrame
	 set applied paragraph style to pStyle
      end tell
      if fitToContent then
	 tell myFrame to fit given frame to content
      else
	 tell myFrame to set vertical justification of text frame preferences to vJust
      end if
      if layerRef is not missing value then
	 set item layer of myFrame to layerRef
      end if
      return myFrame
    end tell
  end tell
end makeTextFrame 

Make Frame - ExtendScript

//Expects document with paragraph and object styles as named
var layerRef = undefined;
var gBounds = [100, 30, 150, 500];
var textContent = "This is a test, only a test";
var fitToCont = false;
var pStylename = "Heading1";
var myFillColor = "Black";
var myFillTint = 30;
var myStrokeWeight = 2;
var myStrokeColor = "Black"
var myStrokeTint = 100;
var frameName = "Text Frame";
app.scriptPreferences.measurementUnit = MeasurementUnits.POINTS;
var vJust = app.textFramePreferences.verticalJustification = VerticalJustification.CENTER_ALIGN;
var docRef = app.documents[0];
var pStyle = docRef.paragraphStyles.item(pStylename);
var pageRef = app.activeWindow.activePage;
var myFrame = makeTextFrame(pageRef, frameName, gBounds, myFillColor, myFillTint, myStrokeWeight,
myStrokeColor, myStrokeTint, pStyle, textContent, vJust, layerRef);

function makeTextFrame (pageRef, frameName, gBounds,  myFillColor, myFillTint, myStrokeWeight, 
myStrokeColor, myStrokeTint, pStyle, textContent, vJust, layerRef) {
  var myFrame = pageRef.textFrames.add({geometricBounds:gBounds, fillColor:myFillColor, 
fillTint:myFillTint, strokeWeight:myStrokeWeight});
  if (myStrokeWeight != 0) {
    myFrame.strokeColor = myStrokeColor;
    myFrame.strokeTint = myStrokeTint;
   }
  if (frameName != "") {
    myFrame.name = frameName;
  }
  if (fitToCont != false) {
    myFrame.fit(FitOptions.FRAME_TO_CONTENT);
  }
  myFrame.texts.item(0).insertionPoints.item(0).contents = textContent;
  myFrame.texts.item(0).parentStory.appliedParagraphStyle=pStyle;
  myFrame.textFramePreferences.verticalJustification= vJust;
  if (layerRef != undefined){
    myFrame.itemLayer = layerRef;
  }
  return myFrame;
}

Add User Interaction

To complete the script, you will want to create a user interaction dialog (UI) to allow the user to define the values for the text frame. The problem with this handler, as with the handler to make a rectangle (makeRectangle) from our previous blog, is that there are a number of variables that need to be defined, requiring a fairly extensive user dialog.

By using a paragraph style, we were able to save having to establish a few more variables. Imagine the number of fields in the UI dialog that would be needed to have the user name the font, size, color, and justification for the text along with all of the other parameters. As you can see, using paragraph styles can simplify scripts with the added advantage of establishing styling consistency.

We can push the concept of using styles further, using object styles to enforce styling consistency while also simplifying an automation script. Let's investigate.

Object Styles

Looking at the script above, we see that it requires 12 arguments to be passed to the makeTextFrame handler. (Don't forget to count vJust which needs to be set inside the tell application block.)

By using an object style to style the text frame, we can cut that number back considerably. But first, let's establish the style. The object style panel is one that I include as part of my workspace. With a new document open, make sure you have a paragraph style established named Heading1. You can set its properties to your liking. Next, open the object style panel. (To open it, select Window > Styles > Object Style from InDesign's menu.)

...Object Style Panel

By default, InDesign gives us three object styes: [None], [Basic Graphics Frame], and [Basic Text Frame]. We will base our new text frame object style on [Basic Text Frame]. Click on [Basic Text Frame] and choose New Object Style from the panel's context menu.

...New Object Style menu

This dialog can be a little intimidating. Just remember, "with complexity, comes power."

Give the style a name: "GrayFillWithBorder." Start at the top of the Basic Attributes list, clicking on Fill and then Stroke. Set the appropriate values when the Fill/Stroke tab panel opens.

...Setting Fill and Stroke in Object Style Window

In the New Object Style window, Basic Attributes list, uncheck Stroke & Corner Options. Make sure Paragraph Styles is checked and click on it. Select Heading1 from the Paragraph Style dropdown.

...Setting Paragraph Style for the Object Style

For the object style, we will set Text Frame General Options to Vertical Justification: Align: Center. Click OK. Alternatively, if you had a text frame selected when you opened the Object Style Options dialog, you could select the Preview option in the lower left corner to preview your settings before dismissing the window.

Using the Object Style

Now, we will write a second script to create a text frame, this time using the object style.

TextFrameWithStyle

AppleScript

set layerRef to missing value
set gBounds to {30, 30, 80, 500}
set textContent to "This is a second test using an object style"
set pStylename to "Heading1"
set oStylename to "GrayFillWithBorder"
tell application "Adobe InDesign CC 2017"
  set measurement unit of script preferences to points
  set docRef to document 1
  set oStyle to object style oStylename of docRef
  set pStyle to paragraph style pStylename of docRef
  set pageRef to active page of active window
  set textFrame to my makeTextFrame(pageRef, "testText", gBounds, oStyle, pStyle, textContent, layerRef)
end tell

on makeTextFrame(parentRef, itemName, gBounds, oStyle, pStyle, textContent, layerRef)
  tell application "Adobe InDesign CC 2017"
    tell parentRef
	set myFrame to make text frame with properties {geometric bounds:gBounds, applied object style:oStyle}
	if itemName is not "" then
	   set name of myFrame to itemName
	end if
	set contents of insertion point 1 of myFrame to textContent
	tell text 1 of parent story of myFrame
	   set applied paragraph style to pStyle
	end tell
	if layerRef is not missing value then
	   set item layer of myFrame to layerRef
	end if
        return myFrame
     end tell
   end tell
end makeTextFrame

ExtendScript

//Expects document with paragraph and object styles as named
var layerRef = undefined;
var gBounds = [30, 30, 80, 500];
var textContent = "This is a second test, using an object style";
var pStylename = "Heading1";
var oStylename = "GrayFillWithBorder";
var frameName = "Text Frame";
app.scriptPreferences.measurementUnit = MeasurementUnits.POINTS;
var docRef = app.documents[0];
var oStyle = docRef.objectStyles.item(oStylename);
var pStyle = docRef.paragraphStyles.item(pStylename);
var pageRef = app.activeWindow.activePage;
var myFrame = makeTextFrame(pageRef, frameName, gBounds, oStyle, pStyle, textContent, layerRef);

function makeTextFrame (pageRef, frameName, gBounds, oStyle, pStyle, textContent, layerRef) {
   var myFrame = pageRef.textFrames.add({geometricBounds:gBounds});
   myFrame.texts.item(0).insertionPoints.item(0).contents = textContent;
   myFrame.appliedObjectStyle = oStyle;
   myFrame.texts.item(0).parentStory.appliedParagraphStyle=pStyle;
   if (layerRef != undefined){
      myFrame.itemLayer = layerRef;
   }
   return myFrame;
}

Now, instead of thirteen arguments, there are only 5 that need to be defined--quite the savings. But wait, there's more!

Using styles, you get:

  • styling that saves with the document should you wish to use the document later as a template
  • styling that exports to HTML for ePub books, and maybe even for a web page.

Export to HTML

For the best HTML export, you will want to associate your paragraph styles with an HTML tag. We will associate our Heading1 style with H1.

...Setting the HTML Tag for the Paragraph Style

A big advantage to using object styles is that InDesign will put the styling into the CSS file that it generates as part of the export. Try it. Export the sample document you created using the two scripts above.

If you check the View HTML after Exporting option, the page you created is displayed automatically.

...Default HTML styling for the Sample Page

As you can see, the displayed page lacks much as far as the page layout is concerned. If you look at the files created as part of the xport, you will see that InDesign has created an .html file and a TestDocument-web-resources folder. If your document had linked image, this folder would contain a folder for the images. For our test, there is only the css folder (Cascading Style Sheets folder). If you open the idGeneratedStyles.css document in a plain text or code editor, you can examine how the paragraph and object styles you created for your document were interpreted for the web.

Looking through the styles, you will find one named the same as your object style with "div." prepended. Also, there is a style named for the Heading1 paragraph style with the associated HTML tag (h1) prepended. The attributes listed under these styles should be fairly self-explanatory. You can give the files to your HTML/CSS person for finalizing, or, feeling brave, add styling to a .css file to make the final product look exactly the way you want (see below). Alternatively, your HTML/CSS person may give you a .css file to add to your export HTML process.

Adding CSS

To illustrate, we will create our own .css file to add to the HTML export. Using a plain text editor (or code editor), create the following file:

div.GrayFillWithBorder {
   width: 500px;
   height: 50px;
   margin: 30px auto 18px auto;
   padding: 30px 12px 12px 12px;
}

Save the file as testCSS.css someplace handy. Make sure it has the .css extension, As a final option, when you export your document, click on the Advanced tab in the HTML Export Options dialog. In the panel that opens, click on the Add Style Sheet button and navigate to the css file created above.

This time, the display of the object-styled text frame is more what we are wanting. To do the same for the second text frame is not that easy as the name InDesign uses to reference the frame can change. Using an object-style, you can have a consistently named and styled text frame when exported to HTML.

...The Sample Page with CSS for Object Style added


Disclaimer: Code samples are to be used as a guide for users to create their own real world scripts and is provided "AS IS". No representation is made as to the accuracy or completeness of the code. Use of the code and its operation is at the discretion and responsibility of the user.

Trackback Link
http://www.yourscriptdoctor.com/BlogRetrieve.aspx?BlogID=18329&PostID=1508088&A=Trackback
Trackbacks
Post has no trackbacks.

Recent Posts


Tags


Archive