Electronic publications with fixed formats rely on absolute positioning. This allows text to be positioned on top of images. Positioning elements on a page is determined in the CSS file. When you export an InDesign document as HTML, the application assumes you are creating a dynamic formatted document where element positioning can change depending on the device, user preference settings, and so on. Consequently, no information is written to the CSS as to the positioning of text or other elements. Of course, in updating the CSS file you can “guestimate” positioning. In this and the next two blogs, we will explore how a script can be used to accomplish this task for you. In the previous four blogs we walked through a script that exports the pages of a document as jpeg files. This leaves the document with all text frames residing on a layer named by the user. For writing our script, we can start with the modified document. That way we can get a list of all text frames using the layer reference.

GET LIST OF TEXT FRAMES

AppleScript

--Assuming that the text layer is named "Text", we can get the list of the document's text frames
set layerName to "Text"
tell application "Adobe InDesign CS6"
--assumes the modified document is open, with measurements set to points
set docRef to document 1
tell docRef
set layerRef to layer layerName of docRef
end tell
set frameList to text frames of layerRef
end tell
frameList

ExtendScript

var layerName = "Text";
var docRef = app.documents.item(0);
var layerRef = docRef.layers.itemByName(layerName);
var frameList = layerRef.textFrames;
frameList.length;

GET FRAME INFO

What we will want our script to do is get the information about each text frame and write the information to a text file. Then, when working with our project’s CSS file, that information will be readily available. When writing a script that needs to work with a number of items in a list, it is best to start with one item in the list for testing. Once this works as anticipated. the repeat loop is easy to add.

We will organize our script using a subroutine to return the text frame information as a string.

AppleScript

(*Returns information for text frame referenced*)
on textFrameInfo(frameRef)
	tell application "Adobe InDesign CS6"
		--get the name of the page the frame is on
		set pName to name of parent page of frameRef
		--get the geometric bounds for the frame
		copy geometric bounds of frameRef to {y0, x0, y1, x1}
		--get the text for the text frame
		set tContent to text 1 of frameRef
	end tell
	--now do the calculations
	set frameWid to x1 - x0
	set frameHgt to y1 - y0
	--create the information string
	set textStr to "page " & pName & " xPosition: " & x0 & " yPosition: " & y0 & " frameWid: " & 
        set textStr to textStr &  " frameHgt: " & frameHgt & " Content: " & tContent
	return textStr
end textFrameInfo 

ExtendScript

function textFrameInfo (frameRef) {
    var pName = frameRef.parentPage.name;
    var gBounds = frameRef.geometricBounds;
    var y0 = gBounds[0];
    var x0 = gBounds[1];
    var y1 = gBounds[2];
    var x1 = gBounds[3];
    var tContent = frameRef.texts.item(0);
    //do calculations
    var frameWid = x1 - x0;
    var frameHgt = y1 - y0;
    //create information string
    var textStr = "page " + pName + " xPosition: " + x0 + " yPosition: " + y0 +" frameWid: " + frameWid 
    textStr +=  " frameHgt: " + frameHgt + " Content: " + tContent;
    return textStr;
 }

CALL HANDLER TO PROCESS FRAME

With this handler in place (at the bottom of the script), all we need to do is add the call to the handler. Placing the textStr variable at the end returns the result of the handler to the Result window for Script Editor (Console for ExtendScript).

AppleScript

--place the following at the bottom of the top portion of the script above: 
set frameRef to item 1 of frameList
set textStr to textFrameInfo (frameRef)
textStr

ExtendScript

//place the following at the bottom of the top portion of the script above:
var frameRef = frameList[0]
var textStr = textFrameInfo (frameRef);
textStr;

ADD REPEAT LOOP

Once you make sure the information being returned is what you want, surround the call to the handler with a repeat loop:

AppleScript

repeat with i from 1 to length of frameList
   set frameRef to item i of frameList --notice the reference is to item i, not 1
   set textStr to textFrameInfo (frameRef)
end repeat

ExtendScript

for (var i = 0; i < frameList.length; i++){
   var frameRef = frameList[i]
   var textStr = textFrameInfo (frameRef);
}

WRITE INFO TO TEXT FILE

Lastly, the script will write the text strings returned to a plain text file. We will create the file in the same folder as the document. For this we need to get the path to the document and use this to construct a file path to the text file.

--inside the tell statement to the document
set docPath to (file path of docRef) as string
--before writing the text to the fie
set filePath to docPath & "FrameInfo.txt"

AppleScript and ExtendScript are quite different in how they handle writing text to files. With AppleScript you set the end of file marker (eof) to 0 to write to a file without append. With ExtendScript the open method starts a new file without append. Otherwise text written to the file is appended.

AppleScript

With each iteration of our repeat loop, the text returned will be written to the file using another handler, “writeToFile_append”. This handler requires a path to the file, the text string, and a boolean (true/false) to indicate if the text is to be appended to the existing file.

(*Writes text string to file given path to file (filePath) and string to write (textStr). Returns length of file.*)
on writeToFile_append(filePath, textStr, doAppend)
	try
	   set fileRef to open for access file filePath with write permission
	on error errStr --in case file not closed is cause for error
           close access fileRef
           set fileRef to open for access file filePath with write permission
	end try
	set fileLength to (get eof fileRef)
	if doAppend = false then
	   set eof fileRef to 0
	   write textStr to fileRef
	else
	   write (return & textStr) to fileRef starting at ((get eof fileRef) + 1)
	end if
	set newLength to (get eof fileRef)
	close access fileRef
	return (newLength - fileLength)
end writeToFile_append

The first time through the loop, we will not append the text. Thereafter, we will want the text to append. The top of our script will now read as follows:

set layerName to "Text" --assumes text layer is named "Text"
set doAppend to false --initialize to false
tell application "Adobe InDesign CS6"
	--assumes that there is a document open
	set docRef to document 1
	tell docRef
	   set docPath to (file path of docRef) as string
	   --assumes all text frames have been moved to layer (layerName variable)
	   set layerRef to layer layerName of docRef
	end tell
	set frameList to text frames of layerRef
end tell
--define file path for text file using folder for document
set filePath to docPath & "FrameInfo.txt"
repeat with i from 1 to length of frameList
        --change item reference to i, rather than 1
	set frameRef to item i of frameList 
	--call handler to get the text frame information 
	set textStr to textFrameInfo(frameRef)
	if i = 2 then set doAppend to true
	writeToFile_append(filePath, textStr, doAppend)
end repeat

ExtendScript

To allow the script to open the file once and close when completed, the write functionality is included in the top portion of the script.

var fileRef = undefined;
var layerName = "Text";
var docRef = app.documents.item(0);
var dPath = docRef.filePath;
var docPath = Folder.decode(dPath);
var layerRef = docRef.layers.itemByName(layerName);
var frameList = layerRef.textFrames;
//establish path for file and write text to file
var writePath = docPath + "/TestExtendScript.txt";
var fileRef = File(writePath);
var fileOpen = fileRef.open("w", "TEXT", "????"); 
if (fileOpen == true) {
for (var i = 0; i < frameList.length; i++){
    var frameRef = frameList[i]
    var textStr = textFrameInfo (frameRef);
    fileRef.writeln(textStr);
}
fileRef.close();
}//end if

To test the script at this point you will need to open the text file created using any plain text editor. The script is just an outline of what we want the script to do as there are a number of assumptions being made. As is often quoted, “the devil is in the details.” We will look at the details in next week’s blog.