DO MORE with Scripting

Automate complex layout and design tasks in Adobe InDesign!

DO MORE with Scripting 3: Typefi Document Object Model (DOM)

Peter Kahrel’s previous DO MORE with Scripting session dealt with how scripts can interact with the Typefi Engine. In this episode Peter looks at a second major component of Typefi scripting—the Typefi Document Object Model (DOM).

The DOM provides scripting access to the Typefi Designer plug-ins, enabling scripts to interact with Typefi items such as Elements, Fields, and Sections. This webinar offers step-by-step demos on accessing the DOM, as well as finding and modifying Elements.

Peter also offers some very useful insights on how the Typefi Engine manages floats, and some traps to avoid when deploying scripts in running Typefi jobs.

Overview

Welcome to this session of DO MORE with Scripting.

In the previous session we dealt with how scripts can interact with the Typefi Engine. Today we’ll deal with a second major component of Typefi scripting, namely, the Typefi Document Object Model (DOM), which is how we interact in our scripts with Typefi items such as Elements, Fields, and Sections. Or, in other words, scripting access to the Typefi Designer plug-ins.

Accessing the Typefi Document Object Model (0:34)

There are two Typefi entry points into the scripting DOM: typefiSettings and autofitSettings. Today we’ll deal only with typefiSettings; autofitSettings will be treated in a separate episode.

Many InDesign objects have the typefiSettings property—for example, text frames—as we can see in the ESTK’s Object Model Viewer (OMV), or any alternative viewer, such as Typefi’s InDesign ExtendScript API which I mentioned earlier.

I’ll almost always use the ESTK’s OMV. It has its detractors but I think it’s OK, probably because I’ve been using it for 15 years or so.

You open the OMV by pressing F1 in the ESTK (or select Object Model Viewer in the Help menu).

Exploring properties (1:22)

The typefiSettings property is a single property but takes on different guises depending on the InDesign object you view it with.

For example, textFrame.typefiSettings leads you to typefiPageItemSettings. Through this you can check whether a frame is a Typefi Element, and if so, the name of the Typefi Element, and if it’s a float, the name of the variant.

Given an Element instance like the following (a floating Element, name ‘Photo’, variant name ‘top’), you can explore its Typefi properties as follows. Select the frame, then:

app.selection[0]
app.selection[0].typefiSettings
app.selection[0].typefiSettings.element
app.selection[0].typefiSettings.element.name
app.selection[0].typefiSettings.element.variantName

When you select another InDesign object in the OMV, its Typefi name changes accordingly. For example, at Page you’ll see that there aren’t many properties and methods, but there’s one that we use a lot in most scripts, namely, the mainStoryFrame() function.

app.documents[0].pages[0].typefiSettings.mainStoryFrame();

To verify this do, for example:

app.documents[0].pages[0].typefiSettings.mainStoryFrame().select();

All these typefiSettings relate to the Typefi plug-ins (Sections, Elements, Fields, and so on). Virtually anything that you can do in the UI you can do with a script (I say ‘virtually’ because not everything is scriptable yet, but soon will be).

Example: Finding the main story on a page (8:11)

The Typefi plug-ins work like all scriptable plug-ins. Let’s explore a little. For example, I mentioned that we very often need to get a handle on the main story on a page. We do that as follows.

I’ll start again with a mini TYPEFI object (see the previous session for details). Remember that we get a handle on the current page by using

TYPEFI.inddPage
but we’re working interactively and we have no Engine, so we use our mini-framework:
TYPEFI = {
	inddPage: app.windows[0].activePage
}

mf = TYPEFI.inddPage.typefiSettings.mainStoryFrame();

if (!mf) {
	$.writeln ('No');
} else {
	$.writeln ('Yes');
}

Example: Finding a Typefi Element on a page (9:03)

I’ll now turn to another page, one with an Element. How do we go about finding an Element on a page? Any Element, and if it’s a float, a particular variant name, for instance.

We’ll do it as follows: get all page items, then check if any is the item you’re looking for. We want to check whether the page contains an Element of type ‘Photo’. We’ll go though the Object Model.

TYPEFI = {
	inddPage: app.windows[0].activePage
}

function findElement () {
	var frames = TYPEFI.inddPage.pageItems.everyItem().getElements();
	for (var i = frames.length-1; i >= 0; i--) {
		if (frames[i].typefiSettings.element.name == 'Photo'
			return frames[i];
		}
	}
	return null;
}

frame = findElement();

This works fine here in the interface, interactively. However, this will often not work in a running job.

TPSPaginationLayer (13:18)

During a document’s pagination, the Typefi Engine keeps floating elements on a special InDesign layer. You won’t see that layer normally because it’s created by the Engine and deleted when the document finishes (you may see it sometimes when you open a document that crashed during composition).

You must therefore always make sure that the item you found is not on that special layer. The name of the layer is TPSPaginationLayer.

TYPEFI = {
	inddPage: app.windows[0].activePage
}

function findElement () {
	var frames = TYPEFI.inddPage.pageItems.everyItem().getElements();
	for (var i = frames.length-1; i >= 0; i--) {
		if (frames[i].typefiSettings.element.name == 'Photo' 
			&& frames[i].itemLayer.name !== 'TPSPaginationLayer') {
			return frames[i];
		}
	}
	return null;
}

frame = findElement();

The pagination layer, then, must be avoided when you’re looking for page items, but equally you must stay away from it when you add a page item. Always make sure that you don’t place anything on the pagination layer, because it’ll be deleted when the Engine deletes the layer.

Example: Placing a mask on a Typefi Element (16:05)

Say we want to place a mask on all our photos. We look for a photo on a page, as we did before, then we place the mask on the photo’s layer, as we know that the photo is not on the pagination layer.

photo = findElement();
TYPEFI.inddPage.textFrames.add (photo.itemLayer, {
	geometricBounds: photo.geometricBounds,
	fillColor: 'Black'
});

Conclusion (18:33)

This concludes the session. In the next episode we’ll present a case study in which the items discussed in this session will be brought together in a script that ensures that floating Elements are placed in their own text section.

< Previous webinar Next webinar >

About Peter Kahrel

Peter was born in Amsterdam, the Netherlands. He trained as a linguist at the University of Amsterdam and has an MA and a PhD, specialising in syntax, semantics, and typology. He has lived in the UK since 1994, working as a typesetter, editor, copy-editor, and indexer (and sometimes as a designer too) for publishers in the UK, the Netherlands, and Germany, preparing for the press both books and journals. He combined this with teaching at the Linguistics Department at Lancaster University.

Peter has been programming InDesign with JavaScript since 2003, mainly to cut out the tedium that faces every typesetter and indexer but in equal measure because it’s good fun. Peter has worked as a script developer at Typefi since 2010, and is highly regarded in the global InDesign scripting community.

Check out Peter’s website—which includes a bunch of free scripts—at www.kahrel.plus.com.

× Shopping Cart

Your cart is empty.