ADOBE® INDESIGN® CS5

ADOBE INDESIGN CS5 SCRIPTING GUIDE: JAVASCRIPT

© 2010 Adobe Systems Incorporated. All rights reserved.

Adobe® InDesign® CS5 Scripting Guide: JavaScript If this guide is distributed with software that includes an end user agreement, this guide, as well as the software described in it, is furnished under license and may be used or copied only in accordance with the terms of such license. Except as permitted by any such license, no part of this guide may be reproduced, stored in a retrieval system, or transmitted, in any form or by any means, electronic, mechanical, recording, or otherwise, without the prior written permission of Adobe Systems Incorporated. Please note that the content in this guide is protected under copyright law even if it is not distributed with software that includes an end user license agreement. The content of this guide is furnished for informational use only, is subject to change without notice, and should not be construed as a commitment by Adobe Systems Incorporated. Adobe Systems Incorporated assumes no responsibility or liability for any errors or inaccuracies that may appear in the informational content contained in this guide. Please remember that existing artwork or images that you may want to include in your project may be protected under copyright law. The unauthorized incorporation of such material into your new work could be a violation of the rights of the copyright owner. Please be sure to obtain any permission required from the copyright owner. Any references to company names in sample templates are for demonstration purposes only and are not intended to refer to any actual organization. Adobe, the Adobe logo, Creative Suite, and InDesign are either registered trademarks or trademarks of Adobe Systems Incorporated in the United States and/or other countries. Microsoft and Windows are either registered trademarks or trademarks of Microsoft Corporation in the United States and/or other countries. Mac OS is a trademark of Apple Computer, Incorporated, registered in the United States and other countries. All other trademarks are the property of their respective owners. Adobe Systems Incorporated, 345 Park Avenue, San Jose, California 95110, USA. Notice to U.S. Government End Users. The Software and Documentation are “Commercial Items,” as that term is defined at 48 C.F.R. §2.101, consisting of “Commercial Computer Software” and “Commercial Computer Software Documentation,” as such terms are used in 48 C.F.R. §12.212 or 48 C.F.R. §227.7202, as applicable. Consistent with 48 C.F.R. §12.212 or 48 C.F.R. §§227.7202-1 through 227.7202-4, as applicable, the Commercial Computer Software and Commercial Computer Software Documentation are being licensed to U.S. Government end users (a) only as Commercial Items and (b) with only those rights as are granted to all other end users pursuant to the terms and conditions herein. Unpublished-rights reserved under the copyright laws of the United States. Adobe Systems Incorporated, 345 Park Avenue, San Jose, CA 95110-2704, USA. For U.S. Government End Users, Adobe agrees to comply with all applicable equal opportunity laws including, if appropriate, the provisions of Executive Order 11246, as amended, Section 402 of the Vietnam Era Veterans Readjustment Assistance Act of 1974 (38 USC 4212), and Section 503 of the Rehabilitation Act of 1973, as amended, and the regulations at 41 CFR Parts 60-1 through 60-60, 60-250, and 60-741. The affirmative action clause and regulations contained in the preceding sentence shall be incorporated by reference.

Contents
1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
How to Use the Scripts in this Document . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 About the Structure of the Scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 For More Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 Other JavaScript development options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

2

Scripting Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Script Preferences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 Getting the Current Script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 Script Versioning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Targeting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Compilation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Interpretation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 13 13 13

Using the doScript Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 Sending parameters to doScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 Returning values from doScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 Controlling Undo with doScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 Working with Script Labels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 Running Scripts at Startup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 Session and Main Script Execution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

3

Documents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
Basic Document Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating a new document . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Opening a document . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Saving a document . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Closing a document . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Basic Page Layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Defining page size and document length . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Defining bleed and slug areas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Setting page margins and columns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Changing the appearance of the pasteboard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Guides and grids . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Changing measurement units and ruler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Defining and applying document presets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Setting up master spreads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Adding XMP metadata . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating a document template . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating watermarks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 20 20 21 21 22 22 23 24 25 26 28 29 31 32 33 37

Adjusting Page Sizes and Layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 Selecting pages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

3

Contents

4

Resizing and reframing pages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 Transforming pages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 Master page overlay . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 Printing a Document . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Printing using page ranges . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Setting print preferences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Printing with printer presets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exporting a Document as PDF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exporting to PDF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Setting PDF export options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exporting a range of pages to PDF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exporting individual pages to PDF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exporting PDF with Interactive Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exporting Pages as EPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exporting all pages to EPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exporting a range of pages to EPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exporting as EPS with file naming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 41 41 44 44 45 45 46 47 48 48 48 48 49

4

Working with Layers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
Understanding the Layer Object Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 Scripting Layers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating layers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Referring to layers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Deleting layers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Moving layers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Duplicating layers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Merging layers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Assigning page items to layers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Setting layer properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 51 51 53 53 53 53 54 54

5

Working with Page Items . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
Creating Page Items . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 Page-item geometry . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 Grouping Page Items . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 Duplicating and Moving Page Items . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating compound paths . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using Pathfinder operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Converting page-item shapes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Arranging page items . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Transforming Page Items . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using the transform method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Working with transformation matrices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Coordinate spaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Transformation origin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Resolving locations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Transforming points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Transforming again . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 60 60 61 62 62 62 63 65 66 67 68 69

Resize and Reframe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Adding text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Applying a font . . . . . . . . . . . . . . . . . 100 About find/change preferences . . . . . . . . . . . . . . . . . . . . . . . . Creating a text frame . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 Working with Tables . . . . . . . . . . . . . . . . . . . . . Text objects and iteration . . . . . . . . . . . . . . . . . . . . . . . . 112 Adding a User Interface to “Hello World” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 Path Text . . . . . . . . . . . . . . . . . . . . . . . . . . 102 Using glyph search . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 71 72 72 73 73 Placing Text and Setting Text-Import Preferences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Importing paragraph and character styles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 Span Columns . . . . . . . . . . . . . . . . . . . . . 77 Understanding Text Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 Finding and changing text formatting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111 Your First InDesign Dialog . 108 Footnotes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 Entering and Importing Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating an anchored frame . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Changing text color . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Working with fonts . . . . . . . . . . . . . . . . Deleting a style . . . . . . . . . . . . . . . Creating and applying styles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 83 83 85 86 86 87 87 89 89 90 90 93 94 94 97 97 99 99 Finding and Changing Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Linking text frames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109 7 User Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Removing a frame from a story . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Unlinking text frames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Working with text selections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 Using grep . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Stories and text frames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Replacing text . . . . . .Contents 5 6 Text and Type . . . . . . . . . . . . . . . . . . . . 111 Dialog Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109 Setting Text Preferences . . . . . . . . . Working with Text Frames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 Exporting Text and Setting Text-Export Preferences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Changing text properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Inserting special characters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Setting text defaults . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Formatting Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Moving and copying text . . . . . 100 Finding and changing text . . . . Splitting all frames in a story . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 Autocorrect . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124 9 Menus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122 Sample Selection Event Listeners . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116 8 Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 ADBE_ScaledGraphics . . . . . . . . . . . . 146 ADBE_BlankPages . . . .Contents 6 Creating a More Complex User Interface . . . . . . . . . . . . . 149 ADBE_CrossReferences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141 Listing preflight data objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 Adding Menus and Menu Items . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140 Listing preflight profiles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 Menus and Events . . . . . . . . . . . . . . 140 Listing preflight rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148 ADBE_BleedSlug . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 Working with ScriptUI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 Sample onIdle Event Listener . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 Sample beforePrint Event Listener . . . . . . . . . . . . . . . . . . . 128 Understanding the Menu Model . . . . . . . . . . 150 ADBE_ImageColorManagement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 About event properties and event propagation . . . . . . . . . . . . . . . . . . . . . . . . . . . 119 Sample afterNew Event Listener . . . . . . . . . . . . . . . . . . . 128 Localization and menu names . . . . . . . . . . . . . . . . . . . . 130 Running a Menu Action from a Script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 Adding Rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150 ADBE_PageCount . . . . . . . . . . . . . . . . . . . . 146 Available Rules . . . . . . . . . . . . . . . . . . . 134 10 Working with Preflight . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149 ADBE_FontUsage . . . . . . . . . . . . . 140 Exploring Preflight Profiles . . . . . . 116 Creating a progress bar with ScriptUI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141 Importing a Preflight Profile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 Understanding the Event Scripting Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149 ADBE_Colorspace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145 Custom Rules . . . . . . . . 132 Working with scriptMenuActions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150 ADBE_ImageResolution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148 ADBE_BleedTrimHazard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 Processing a Profile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 ADBE_PageSizeOrientation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 Working with Event Listeners . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 A More Complex Menu-scripting Example . . . . . . . . . . . . . . . . 142 Creating a Preflight Profile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168 Saving XML tags . . 153 Creating Buttons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152 ADBE_SpotColorSetup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169 Working with XML attributes . . . . . . . . . . . . . . . . . . . . . . 162 Design options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171 Associating XML elements with page items and text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158 TimingSettings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174 Working with XML tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152 11 Creating Dynamic Documents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164 12 XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169 Working with XML stories . . . . . . . . . . . . . . . . . . . . . . . . . . .Contents 7 ADBE_ScaledType . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163 Adding Page Transitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162 Motion presets . 165 The Best Approach to Scripting XML in InDesign . . . . . . . . . . . . . . . . . . . . . . . 154 Creating Multistate Objects . . . . . . . . . . . . . . . . . . . 165 Scripting XML Elements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153 Importing Movies and Sounds . 158 Basic animation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166 Setting XML preferences . . . . . . . . . . . . . . 172 Applying styles to XML elements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168 Duplicating an XML element . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168 Creating an XML element . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167 Loading XML tags . . . 166 Setting XML import preferences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170 Adding XML Elements to a Layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167 Creating an XML tag . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163 Key frames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171 Marking up existing layouts . . . . . . . . . . . . . . . . . . . . 178 . 152 ADBE_TransparencyBlending . . . . . . . . . . . . . . . . . . . . . . 151 ADBE_SmallText . . . . . . 152 ADBE_TextOverrides . . . . . . . . . . . . . . . . . . . . . . . . . . . 156 Working with Animation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168 Moving an XML element . . . . . . . . . . . . . . . . . . . . . . . . . 170 Exporting XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166 Importing XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169 Creating an XML processing instruction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159 Animating transformations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168 Removing items from the XML structure . . . . . . . . . . . . . . . . . . . . . . . . 152 ADBE_StrokeRequirements . 169 Creating an XML comment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175 13 XML Rules . . . . . . 168 Deleting an XML element . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190 Duplicating XML elements with XML rules . . . . . . . . 185 Setting up a sample document . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202 Creating Tables using XML Rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194 Finding XML elements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198 Applying formatting with XML rules . . . . . . . . . . . . . 179 XML Rules Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206 Navigating tracked changes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199 Creating page items with XML rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206 Tracking Changes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179 XML-rules programming model . . . . . . . . . . . . . . . 207 Information about tracked changes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207 Preferences for Tracking Changes . . . 203 Scripting the XML-rules Processor Object . . . . . . . . . . . . . . . . . . . 192 Applying multiple matching rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206 Accepting and reject tracked changes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191 XML rules and XML attributes . . . . . . . . . . . . . . . . . 195 Extracting XML elements with XML rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Contents 8 Why use XML rules? . . . . . . . . . . . . . . . . . . . . 204 14 Track Changes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186 Changing the XML structure using XML rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185 Getting started with XML rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1 Introduction This document shows how to do the following: Work with the Adobe® InDesign® scripting environment. at: http://www. Most of the time. After you have downloaded and expanded the archive. They are only fragments of scripts. ellipses. Customize and add menus and create menu actions.com/products/indesign/scripting/index. Use advanced scripting features. that scripts copied out of this document may contain line breaks and other characters (due to the document layout) that will prevent them from executing properly. graphic lines. Apply XML rules. About the Structure of the Scripts The script examples are all written using a common template that includes the functions “main. install. polygons. A zip archive of all of the scripts shown in this document is available at the InDesign scripting home page. You can copy the script lines shown in this document and paste them into your script editor. you can run the scripts from the Scripts panel inside InDesign. the scripts shown in this document are not complete scripts. At that point.” “mySetup. and are intended to show only the specific part of a script relevant to the point being discussed in the text.html. and exporting.adobe. in addition. including finding and changing text. Work with text and type in an InDesign document. If you need to know how to connect with your scripting environment or view the InDesign scripting object model from your script editor.” and “myTeardown. Perform basic document tasks like setting up master spreads. the part of the script you will be interested in will be inside the “mySnippet” function. a new scripting feature that makes working with XML in InDesign faster and easier. from creating XML elements and importing XML to adding XML elements to a layout.” “mySnippet. Work with XML. and run scripts. Work with page items (rectangles. Create dialog boxes and other user-interface items. that information can be found in the Adobe InDesign CS5 Scripting Tutorial. move the folders corresponding to the scripting language(s) of your choice into the Scripts Panel folder inside the Scripts folder in your InDesign folder. text frames. but you should not expect them to run without further editing.” We did this to simplify automated testing and publication—there is no reason for you to construct your scripts this way. 9 . Note. and groups). How to Use the Scripts in this Document For the most part. Respond to user-interface events. printing. We assume that you have already read the Adobe InDesign CS5 Scripting Tutorial and know how to create.

adobeforums. . or you can use the Creative Suite Extension Builder (CS Extension Builder) to develop CS extensions in ActionScript. we recommend using the Creative Suite ActionScript Wrapper Library (CSAWLib). CS Extension Builder allows you to design the user interface interactively using the Design view of FlashBuilder.com. post answers. In CS5. For details of how to use CS Extension Builder and the wrapper libraries. CS5 includes the Extension Manager to enable installation of CS5 extensions. using the Flex framework. properties. you also can visit the InDesign Scripting User to User forum. It also allows you to develop all of the application logic for your CS5 extension in ActionScript. which is accessible from within the Flash Builder or Eclipse Help system when you have installed CS Extension Builder. and each CS5 extension is delivered as a compiled Flash (SWF) file. and share their newest scripts.CHAPTER 1: Introduction For More Information 10 For More Information For more information on InDesign scripting. Photoshop and Illustrator. The forum contains hundreds of sample scripts. but has different logic in each. This is tightly integrated with the CS Extension Builder environment. and behavior of the scripting DOM is as described in the JavaScript Scripting Reference for the host application. and run and debug your code against suite applications such as Adobe InDesign. which exposes the scripting DOM of each host application as an ActionScript library. which includes wizards to help you build your extension’s basic structure. adapted to the host application. Kuler has a consistent user interface across the different suite applications. The user interface for an extension is written in ActionScript. An example of a CS5 extension that ships with the point products is Adobe Kuler. scripters can ask questions. the applications have an extensibility infrastructure that allows developers to extend the capabilities of the applications. you can develop and debug your extension in the familiar FlashBuilder environment. see the Creative Suite SDK documentation. CS extensions are Flash-based (SWF) and can potentially work in a variety of Creative Suite applications. In the forum. Other JavaScript development options You can use the ExtendScript Toolkit to create JavaScript scripts explicitly for InDesign. the infrastructure is based on Flash/Flex technology. A C5S extension is typically accessed through its own menu item in the application’s Extensions menu. To develop your application logic. The methods. at http://www.

This property is an array of arrays. A list of the available scripts. the features in this chapter control how scripts operate. Controlling the ExtendScript engine in which scripts execute. Script Preferences The scriptPreferences object provides objects and properties related to the way InDesign runs scripts. filePath]. By contrast..2 Scripting Features This chapter covers scripting techniques related to InDesign’s scripting environment.. Using the doScript method to run scripts. install. . The path to the scripts folder. 11 . We assume that you have already read Adobe InDesign CS5 Scripting Tutorial and know how to write. Almost every other object in the InDesign scripting model controls a feature that can change a document or the application defaults. in the following form: [[fileName. Working with script labels. This document discusses the following: The scriptPreferences object and its properties. Running scripts at InDesign start-up. and run InDesign scripts in the scripting language of your choice. Running scripts in prior versions of the scripting object model. You can use this feature to check for the existence of a script in the installed set of scripts. Getting a reference to the executing script.] Where fileName is the name of the script file and filePath is the full path to the script. The following table provides more detail on each property of the scriptPreferences object: Property enableRedraw scriptsFolder scriptsList Description Turns screen redraw on or off while a script is running from the Scripts panel.

To avoid this alert.CHAPTER 2: Scripting Features Getting the Current Script 12 Property userInteractionLevel Description This property controls the alerts and dialogs InDesign presents to the user. Only scripts run from the Scripts palette appear in the activeScript property.activeScript. using the activeScript property returns an error. To avoid this error and create a way of debugging scripts that use the activeScript property. version Getting the Current Script You can get a reference to the current script using the activeScript property of the application object. alert("The folder containing the active script is: " + myParentFolder). } catch(myError){ return File(myError. Set it to interactWithAll to restore the normal display of alerts and dialogs.parent.fileName). You can use this property to help you locate files and folders relative to the script. alert("The current script is: " + myScript). as shown in the following example (from the ActiveScript tutorial script): var myScript = app. The mechanics of targeting are language specific. see “Script Versioning” on page 12. InDesign does not display any alerts or dialogs. Set it to UserInteractionLevels. .e. var myParentFolder = File(myScript). Note this property is not the same as the version of the application. The version of the scripting environment in use. InDesign displays an alert for missing fonts or linked graphics files. the current version).neverInteract before opening the document. then restore user interaction (set the property to interactWithAll) before completing script execution.activeScript. often. the activeScript property returns an error. When you debug scripts from the ExtendScript Toolkit. When you debug scripts using a script editor. } } Script Versioning InDesign CS5 can run scripts using earlier versions of the InDesign scripting object model. The ability to turn off alert displays is very useful when you are opening documents via script. For more information. When you set this property to UserInteractionLevels.neverInteract. set the user-interaction level to UserInteractionLevels. use the following error handler (from the GetScriptPath tutorial script): function myGetScriptPath() { try{ return app..interactWithAlerts to enable alerts but disable dialogs. To run an older script in a newer version of InDesign. you must consider the following: Targeting — Scripts must be targeted to the version of the application in which they are being run (i.

The following examples show how to set the version to the CS3 (5. which JavaScript has. //Set to 5. The script can be in the same scripting language as the current script or another scripting language. The available languages vary by platform: on Mac OS®. Using the doScript Method The doScript method gives a script a way to execute another script.0 Scripts (for InDesign CS3 scripts) or Version 2. The script can be a string of valid scripting code or a file on disk. the application uses the same version of the DOM that is set for interpretation. The doScript method has many possible uses: Running a script in another language that provides a feature missing in your main scripting language.0" //target the latest version of InDesign #target "InDesign" Compilation JavaScripts are not precompiled. To do this. For compilation. run the script from a folder in the Scripts panel folder named Version 5. you can run AppleScript or JavaScript. on Windows®. which allows a script to get/set the version of the scripting object model to use for interpreting scripts. The version defaults to the current version of the application and persists. which are what the application understands. In all these examples.scriptPreferences.0 scripting object model app.0) version of the scripting object model. or explicitly set the application's script preferences to the old object model within the script (as shown below). JavaScript does not have a way to query Microsoft® Excel for the contents of a specific spreadsheet cell. the doScript method can execute a snippet of scripting code in another language. Put the previous version scripts in the folder. and run them from the Scripts panel. For example.0 Scripts (for InDesign CS2 scripts). Targeting Targeting for JavaScripts is implicit when the script is launched from the Scripts panel. but both AppleScript and VBScript have this capability. but JavaScript performs these calculations rapidly. AppleScript can be very slow to compute trigonometric functions (sine and cosine).version = 5. Interpretation The InDesign application object contains a scriptPreferences object. . use the target directive: //target CS5 #target "InDesign-6. InDesign CS5 correctly interprets a script written for an earlier version of the scripting object model. The mechanics of compilation are language specific. VBScript lacks the ability to display a file or folder browser. to overcome a limitation of the language used for the body of the script. VBScript or JavaScript.0.CHAPTER 2: Scripting Features Using the doScript Method 13 Compilation — This involves mapping the names in the script to the underlying script ids. If the script is launched externally (from the ESTK). Interpretation — This involves matching the ids to the appropriate request handler within the application.

} else{ var myAppleScript = "tell application \"Adobe InDesign CS5\\rdisplay dialog(\"First argument\" & item 1 of arguments & return & \"Second argument: \" & item 2 of arguments & return & end tell". var myJavaScript = "alert(\"First argument: \" + arguments[0] + \"\\rSecond argument: \" + arguments[1]). which it can then execute using the doScript method. myParameters). Sending parameters to doScript To send a parameter to a script executed by doScript. but you can return multiple values by returning an array (for the complete script. an object can contain a script that controls its layout properties or updates its content according to certain parameters.fs == "Windows"){ var myVBScript = "msgbox arguments(1). Scripts can use the doScript method to run scripts that were saved as strings in the label property of objects. myParameters). This is a great way to create a custom dialog or panel based on the contents of the selection or the attributes of objects the script creates. if(File.CHAPTER 2: Scripting Features Using the doScript Method 14 Creating a script “on the fly. This example uses a JavaScript that is executed as a string. app.doScript(myAppleScript.doScript(myVBScript. . "Your message here. myParameters).doScript(myJavaScript. Scripts also can be embedded in XML elements as an attribute of the element or as the contents of an element. ScriptLanguage. See “Running Scripts at Startup” on page 18. ScriptLanguage. Embedding scripts in objects."]. ScriptLanguage.".visualBasic.applescriptLanguage. vbOKOnly. use the following form (from the DoScriptParameters tutorial script): var myParameters = ["Hello from DoScript". Using this technique. This example returns a single value.javascript. refer to the DoScriptReturnValues script). but the same method works for script files. app.” Your script can create a script (as a string) during its execution. \"First argument: \" & arguments(0)". } Returning values from doScript The following script fragment shows how to return a value from a script executed by doScript. app.

ScriptLanguage.id. the parameters //will not be passed to the script. app. var myJavaScript = "var myDestinationPage = arguments[1]. var p2 = "\"This is the first script argument value.item(myDestinationPage)). myArguments). p6. var myDocument = app. myPageIndex.pages.\r" . var myID = myTextFrame. var myJavaScript = p1 + p2 + p3 + p4. "288pt"].\r".pageItems. p2 = "myInDesign. var myPageIndex = myDestinationPage. //Change the text in the duplicated text frame. myJavaScript += "myPageItem. var myScriptArgumentA = app.add(). If it does. alert(nameA + ": " + myScriptArgumentA + "\r" + nameB + ": " + myScriptArgumentB). var myDuplicate = app. ScriptLanguage.add().getValue(nameA).visualBasic).\").item(0). the doScript //statement must not appear inside a function.documents. ". var p4 = "\"This is the second script argument value.scriptArgs.documents. p1 = "Set myInDesign = CreateObject(\"InDesign. "." myJavaScript += "var myPageItem = app. var myScriptArgumentB = app.". var myTextFrame = myPage. see DoScriptScriptArgs): var nameA = "ScriptArgumentA".documents.name.after. "288pt".item(0). var myDestinationPage = myDocument. ". myJavaScript += "var myY = arguments[3]\r.SetValue \"" + nameB + "\".scriptArgs. //myDuplicate now contains a reference to the duplicated text frame.scriptArgs. var p3 = "app.geometricBounds = ["72pt".contents = "Duplicated text frame.scriptArgs. if(File. var myArguments = [myID.\"".\r". ".\r".\")".Application.doScript(myVBScript.javascript. 0. Another way to get values from another script is to use the scriptArgs (short for “script arguments”) object of the application. var nameB = "ScriptArgumentB". } else { .CHAPTER 2: Scripting Features Using the doScript Method 15 //To send parameters to a script run using app.pages.item(0). //Used later. myJavaScript += "var myX = arguments[2].ScriptArgs.add(LocationOptions. var nAc = nameA + ": ".pages.getValue(nameB).ScriptArgs.itemByID(myID).contents = "Example text frame.textFrames.fs == "Windows") { //Create a string to be run as a VBScript.duplicate(app. myTextFrame.setValue(\"" + nameB + "\". myDuplicate.pages. p3 = "\"This is the first script argument value. myJavaScript += "myID = arguments[0]. The following script fragment shows how to do this (for the complete script. var myVBScript = p1 + p2 + p3 + p4 + p5.". var nBc = nameB + ": ". "72pt".CS5\")\r".doScript(). var p5.item(0). var myPage = myDocument. //Create a string to be run as a JavaScript. myPage). var p1 = "app.setValue(\"" + nameA + "\".SetValue \"" + nameA + "\". p5 = "\"This is the second script argument value. p4 = "myInDesign.doScript(myJavaScript.\"\r". 0].\r".\r" //Create an array for the parameters we want to pass to the JavaScript. myTextFrame.

For scripts. p5 = "set value name\"" + nameB +"\" value ". ovals. polygons. These parameters are shown in the following examples: //Given a script "myJavaScript" and an array of parameters "myParameters". InDesign writes to disk. //UndoModes. p6 = "\"This is the second AppleScript script argument value. this does not present any problem. documents. This property can store a very large amount of text.\"" +"\r".applescriptLanguage). you cannot set or view the label using the Script Label panel.fastEntireScript. UndoModes.CHAPTER 2: Scripting Features Controlling Undo with doScript 16 //Create a string to be run as a AppleScript. including page items (rectangles. pages. Controlling Undo with doScript InDesign gives you the ability to undo almost every action. //UndoModes can be: //UndoModes..scriptArgs.javascript. . table cells. ScriptLanguage. For normal work you using the tools presented by the user interface. stories. which can perform thousands of actions in the time a human being can blink.scriptArgs. The label of page items can be viewed.autoUnto: Add no events to the Undo queue. } var myScriptArgumentA = app. ScriptLanguage. //UndoModes. p7 = "end tell" + "\r" p8 = "end tell" + "\r" var myAppleScript = p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8. groups. "Script Action"). shown below. You also can add a label to an object using scripting.doScript(myJavaScript. For many objects. The doScript method offers a way around this performance bottleneck by providing two parameters that control the way that scripts are executed relative to InDesign’s Undo behavior. or edited using the Script Label panel (choose Window > Utilities > Script Label to display this panel). and graphic lines).scriptRequest: Undo each script action as a separate event. and paragraph styles. app.. Working with Script Labels Many objects in InDesign scripting have a label property. //The last parameter is the text that appears in the Undo menu item. p2 = "tell script args" +"\r".fastEntireScript: Put a single event in the Undo queue.getValue(nameB). app.doScript(myAppleScript. p4 = "\"This is the firest AppleScript script argument value. and you can read the script label via scripting. like stories. p3 = "set value name\"" + nameA +"\" value ".\"" +"\r". myParameters. p1 = "tell application \"Adobe InDesign CS5\"\r".entireScript: Put a single event in the Undo queue. and pages. but this comes at a price: for almost every action you make. var myScriptArgumentB = app. entered. the constant disk access can be a serious drag on performance.getValue(nameA). alert(nAc + myScriptArgumentA + nBc + myScriptArgumentB). //UndoModes. text frames.

myEnd.").item(i). var myPage = myDocument. for(var i = 0.pageItems. such as tab. i++) { if(myPage. myY1. as shown in the following script fragment (from the CustomLabel tutorial script): . myRectangle. A script can set a custom label using the insertLabel method.pageItems. myY2.myStart. colors. } In addition.or comma-delimited text. } else { myRandom = myStart + Math.add({geometricBounds:[myY1.pageHeight. } return myRandom. } } alert("Found " + count + " page items with the label.pages. for(var i = 0. myPageHeight.rectangles. false). false).documentPreferences.pageWidth. //<fragment> //Create 10 random page items.round(Math. i < myPage. The following script fragment demonstrates this special case of the label property (for the complete script.random()*myRange). or layers) can be referred to by their name.label == "myScriptLabel") { count++. they can be stored in the label property. 1.add(). false). and extract the custom label using the extractLabel method. i++) { myX1 = myGetRandom(0. if(myInteger == true) { myRandom = myStart = Math. } } var count = 0. var myPageHeight = myDocument. all objects that support the label property also support custom labels. myY2. true)) { myRectangle.item(0). var myRange = myEnd .CHAPTER 2: Scripting Features Working with Script Labels 17 The label property can contain any form of text data.floor(Math.documentPreferences. myRectangle = myPage. see ScriptLabel): var myDocument = app. myPageWidth.length. Because scripts also are text.random()). myX2]}). i < 10. myInteger) { var myRandom. myY2 = myGetRandom(0. false). var myPageWidth = myDocument. myX2. HTML. var myX1. or XML.documents. Page items can be referred to by their label.label = "myScriptLabel". myX1. if(myGetRandom(0. myY1 = myGetRandom(0. myPageHeight. //This function gets a random number in the range myStart to myEnd. just like named items (such as paragraph styles. function myGetRandom(myStart. myX2 = myGetRandom(0. myPageWidth.

the script is interpreted and executed by the “main” ExtendScript engine. var myRectangle = myPage. use the #targetenging statement and provide your own ExtendScript engine name. which is destroyed when the script completes execution. 144.documents. as shown in the following script fragment: #targetengine "adobe" . var myPage = myDocument.rectangles. myDocument. var myString = myRectangle.extractLabel("CustomLabel"). To do this. //Insert a custom label using insertLabel. session and main. For more information.points. 72. 144]}).horizontalMeasurementUnits = MeasurementUnits.viewPreferences. the second is the text to add to the label.viewPreferences. Session and Main Script Execution InDesign has two ways to run a JavaScript. "This is some text stored in a custom label. see “Session and Main Script Execution” on page 18. Script objects created by the script do not persist.CHAPTER 2: Scripting Features Running Scripts at Startup 18 var myDocument = app. Running Scripts at Startup To run a script when InDesign starts.add().points."). You can refer to these objects from other scripts run in the session engine. when you run an InDesign JavaScript. see “Installing Scripts” in Adobe InDesign CS5 Scripting Tutorial).insertLabel("CustomLabel". #targetengine "session" You can create your own persistent ExtendScript interpretation and execution environment. alert("Custom label contained: " + myString).item(0). By default. put the script in the Startup Scripts folder in the Scripts folder (for more information. //Extract the text from the label and display it in an alert. myRectangle. To set the session engine as the target of an InDesign JavaScript.pages.verticalMeasurementUnits = MeasurementUnits. The first parameter is the //name of the label.add({geometricBounds:[72. These names correspond to the ExtendScript “engine” used to run the script. NOTE: Scripts run in the session ExtendScript engine when InDesign starts can create objects and functions that will be available to other scripts for the duration of the session. add the following line to the start of your script. myDocument. Scripts run in the session engine can create objects that persist until you close InDesign.

Export a document as Adobe PDF. Set up master pages (master spreads) Set text-formatting defaults. printing or exporting them. Create a document template. saving them. Add XMP metadata (information about a file). Closing a document. Change measurement units and ruler origin. Apply different sizes to different pages (multiple pages sizes). Use guides and grids. Saving a document. install. Change the appearance of the pasteboard. colors. We assume that you have already read Adobe InDesign CS5 Scripting Tutorial and know how to create. Specifying page columns and margins. Perform basic page-layout operations. and text. Opening a document. This chapter shows you how to do the following Perform basic document-management tasks. Print a document. and populating them with page items. Export pages of a document as EPS.3 Documents The work you do in InDesign revolves around documents—creating them. including: Setting the page size and document length. Create watermarks. and run a script. styles. 19 . Defining bleed and slug areas. including: Creating a new document. Define and apply document presets. Almost every document-related task can be automated using InDesign scripting.

create a new window. //At this point. closing. Hidden documents are not minimized. hide it) by setting the showing window parameter of the open method to false (the default is true). //To show the window: var myWindow = myDocument.CHAPTER 3: Documents Basic Document Operations 20 Basic Document Operations Opening. (For the complete script. var myDocument = app. scripts will run faster when the document //window is not visible. You might want to do this to improve performance of a script. you could do things with the document without showing the //document window. see MakeDocument. and saving documents are some of the most basic document tasks.documents. false).open(File("/c/myTestDocument. To show a hidden document.) var myDocument = app. To create a document using a document preset. var myDocument = app. This section shows how to do them using scripting. //Replace "myDocumentPreset" in the following line with the name //of the document preset you want to use. //The first parameter (showingWindow) controls the visibility of the //document. Some script operations are much faster when the document window is hidden.add(). see OpenDocument. Creating a new document The following script shows how to make a new document using scripting. Opening a document The following script shows how to open an existing document. . In some cases.windows.) //Creates a new document using the specified document preset. create a new window.add(true.indd"). (For the complete script.documents.item("myDocumentPreset")). as shown in the following script fragment (from the OpenDocumentInBackground tutorial script): //Opens an existing document in the background.add(false). as shown in the following script. the add method includes an optional parameter you can use to specify a document preset. You can choose to prevent the document from displaying (that is. and will not appear until //you add a new window to the document. //When you want to show the hidden document.add(). then shows the document. see MakeDocumentWithPreset. app. as shown in the following script fragment (from the MakeDocumentWithParameters tutorial script): //Creates a new document without showing the document window.) app.documentPresets. var myDocument = app. var myLayoutWindow = myDocument.indd")).documents.windows. You can create a document without displaying it in a window. (For the complete script.add().open(File("/c/myTestDocument. //You'll have to fill in your own file path.

true).close().activeDocument.saved == false){ //If you do not provide a file name.indd".activeDocument.indd")). save it.modified == true){ app. //If the file name contains the extension ". if(myFileName.save(new File("/c/myTestDocument.documents.activeDocument.activeDocument. and you save a file to another file name by choosing File > Save As.CHAPTER 3: Documents Basic Document Operations 21 Saving a document In the InDesign user interface. ". if(app. save it.fullName + "". The close method can take up to two optional parameters.activeDocument. } app. myFileName = app. then give it a default file name/file path. as shown in the following script fragment (from the SaveAsTemplate tutorial script): //Save the active document as a template. } The save method has two optional parameters: The first (to) specifies the file to save to. var myFileName. if(app.save(). InDesign displays the Save dialog box. } } //If the document has not been saved.indt").replace(myRegularExpression. as shown in the following script fragment (from the CloseWithParameters tutorial script): .indt".close().save(File(myFileName).activeDocument. Closing a document The close method closes a document. if(app. change it to ".indd/gi myFileName = myFileName. } You can save a document as a template. //Note that you could also use: //app.activeDocument.indt". else{ myFileName = "/c/myTestDocument. the second (stationery) can be set to true to save the document as a template.activeDocument. you save a file by choosing File > Save. as shown in the following script fragment (from the SaveDocumentAs tutorial script): //If the active document has not been saved (ever).item(0). as shown in the following script fragment (from the CloseDocument tutorial script): app.saved == true){ //Convert the file name to a string. In InDesign scripting.indexOf(".indd")!=-1){ var myRegularExpression = /. as shown in the following script fragment (from the SaveDocument tutorial script): //If the active document has been changed since it was last saved. app. the save method can do either operation.

myFile). myCounter--){ app.yes.activeDocument. Defining page size and document length When you create a new document using the InDesign user interface. display a prompt. as shown in the following script fragment (from the DocumentPreferences tutorial script): var myDocument = app. to save to a specific file name: //var myFile = File("/c/myTestDocument. as shown in the following script fragment (from the CloseAll tutorial script): for(myCounter = app.documents. .close(SaveOptions.documents. and whether the document uses facing pages. all these parameters are accessible to scripting. with(myDocument. pagesPerDocument = 16. use the documents. } You can close all open documents without saving them. assigned number of pages.CHAPTER 3: Documents Basic Page Layout 22 //Use SaveOptions.no to close the //document without saving. // //If the file has not been saved. To create a document using InDesign scripting. or SaveOptions. Again.activeDocument.activeDocument. } else{ //If the file has already been saved.length.close(SaveOptions. pageWidth = "600pt".yes to save the document.indd"). myCounter > 0.saved != true){ app.item(myCounter-1).yes).close(SaveOptions.ask to display a prompt. pageOrientation = PageOrientation.ask).activeDocument. If //you use SaveOptions. You can also set individual page sizes.landscape. which does not specify these settings. number of pages. You can set the application defaults for page height. After creating a document. you'll need to provide a reference to a file //to save to in the second parameter (SavingIn).no).yes. and columns and margins to define the area into which material is placed. you can specify the default page size.documents. //Or. } NOTE: The app object also has a documentPreferences object. //Note that the file path is provided using the JavaScript URI form //rather than the platform-specific form. and other properties by changing the properties of this object. as shown in the examples in this section. bleed and slug working areas.SaveOptions. if(app. save it. //app.add().add method. see “Adjusting Page Sizes and Layout”. you can use the documentPreferences object to control the settings. page orientation.close(SaveOptions. app. page width. } Basic Page Layout Each document has a default page size.documentPreferences){ pageHeight = "800pt".

myDocument = app. with(myDocument. (For the complete script. see BleedAndSlug. //The bleed properties belong to the documentPreferences object. } Alternately. Typically. you can use the documentSlugUniformSize property. with(myDocument. //The bleed and slug properties belong to the documentPreferences object. //Slug slugBottomOffset = "18p". //The slug properties belong to the documentPreferences object. slugTopOffset = "3p". documentBleedTopOffset = "3p".documents. The two areas can be printed and exported independently.documents.add(). This property is not in the documentPreferences object.) myDocument = app. for example. instead.documentPreferences){ //Bleed documentBleedUniformSize = true. documentBleedOutsideOrRightOffset = "3p". slugTopOffset = "3p". as shown in the following script fragment (from the BleedSlugGuideColors tutorial script): . you might want to omit slug information for the final printing of a document. myDocument = app. if all the bleed distances are equal.documentPreferences){ //Bleed documentBleedBottomOffset = "3p".documents. as in the preceding example. } If all the slug distances are equal. with(myDocument.add(). slugRightOrOutsideOffset = "3p". documentBleedTopOffset = "3p". } In addition to setting the bleed and slug widths and heights.CHAPTER 3: Documents Basic Page Layout 23 Defining bleed and slug areas Within InDesign. The following script shows how to set up the bleed and slug for a new document.documentPreferences){ //Slug: documentSlugUniformSize = true. a bleed or a slug is an area outside the page margins that can be printed or included in an exported PDF. as shown in the following script fragment (from the UniformBleed tutorial script): //Create a new document. you can control the color used to draw the guides defining the bleed and slug. you can use the documentBleedUniformSize property. these areas are used for objects that extend beyond the page edges (bleed) and job/document information (slug). as shown in the following script fragment (from the UniformSlug tutorial script): //Create a new document. it is in the pasteboardPreferences object. slugInsideOrLeftOffset = "3p". documentBleedInsideOrLeftOffset = "3p".add().

. as shown in the following script fragment (from the PageMarginsForOnePage tutorial script): myDocument = app. slugGuideColor = UIColors. "right" means outside. These margins are applied to all pages of the document. then sets the margins and columns for all pages in the master spread. 192]. bottom = "6p" //When document.facingPages == true. you can easily set the correct margin sizes as you create the document. however.or you can specify an array of RGB values (with values from 0 to 255) //bleedGuideColor = [0.documents. it uses the application’s default-margin preferences. } Setting page margins and columns Each page in a document can have its own margin and column settings. 198.pages. for individual newspaper advertisements) using the InDesign user interface.CHAPTER 3: Documents Basic Page Layout 24 with(app. with (myDocument. . Setting the document margin preferences affects only new pages and has no effect on existing pages. //slugGuideColor = [192. with (myDocument.item(0).) myDocument = app. left = "6p" right = "4p" top = "4p" } InDesign does not allow you to create a page that is smaller than the sum of the relevant margins. //"left" means inside. including master pages. //columnGutter can be a number or a measurement string. If you are creating very small pages (for example.add(). From scripting. (For the complete script.pages. With InDesign scripting.facingPages == true.marginPreferences){ columnCount = 3. "right" means outside.activeDocument.pasteboardPreferences){ //Any of InDesign's guides can use the UIColors constants.cuteTeal. and the height of the page must be greater than the sum of the top and bottom margins. InDesign does not change the page size.documents.. the solution is not as clear: when you create a document.documentPreferences. 192. bleedGuideColor = UIColors. //columnGutter can be a number or a measurement string.item(0).. see PageMargins.. columnGutter = "1p". these properties are part of the marginPreferences object for each page. 192].documentPreferences. columnGutter = "1p". //. use the margin preferences for that page. that is.charcoal. This following sample script creates a new document. If you try to set the page height and page width to values smaller than the sum of the corresponding margins on any existing pages. //"left" means inside. by entering new values in the document default page Margin fields in the New Document dialog box. the width of the page must be greater than the sum of the left and right page margins.marginPreferences){ columnCount = 3.add(). left = "6p" right = "4p" top = "4p" } To set the page margins for an individual page. bottom = "6p" //When document.

myDocument. myDocument. //Reset the application default margin preferences to their former state.top = 0.right = 0. myDocument.documentPreferences.marginPreferences.marginPreferences.pages. You can use it for temporary storage of page items or for job-tracking information.documentPreferences.pageHeight = "1p".top = 0.pages. The first is to set the margins of the existing pages before you try to change the page size.pageWidth = "6p".add().masterSpreads. myDocument.item(1).masterSpreads.marginPreferences.documentPreferences.pages.documents. var myY1 = top. myDocument.item(0). The previewBackgroundColor property sets the color of the pasteboard in Preview mode.left = 0. Alternately.item(1).masterSpreads.masterSpreads.top = 0.marginPreferences.item(0). myDocument. myDocument.item(0).pages. //The following assumes that your default document contains a single page.item(0).item(0). //The following assumes that your default master spread contains two pages. bottom = myY2. myDocument.marginPreferences.documents.marginPreferences.item(0).marginPreferences.item(0). myDocument. myDocument. myDocument.pages.pages.marginPreferences){ top = myY1.bottom = 0.left = 0.marginPreferences. right = 0.documentPreferences. bottom = 0. myDocument. left = 0. as shown in the following script fragment (from the PageMarginsForSmallPages tutorial script): var myDocument = app.CHAPTER 3: Documents Basic Page Layout 25 There are two solutions. top = 0.bottom = 0.add().pages.marginPreferences. var myY2 = bottom.item(0).item(0).marginPreferences.pageHeight = "1p".pages.top = 0.item(0).masterSpreads. myDocument. left = myX1 . myDocument.masterSpreads. as shown in the following script fragment (from the PasteboardPreferences tutorial script): . right = myX2.item(0).item(0). as shown in the following script fragment (from the ApplicationPageMargins tutorial script): with (app. you can change the application’s default-margin preferences before you create the document. var myX1 = left. myDocument. myDocument.item(0). myDocument.marginPreferences.item(1).left = 0.pages. You can change the size of the pasteboard and its color using scripting.marginPreferences.item(0).pages.marginPreferences. } Changing the appearance of the pasteboard The pasteboard is the area that surrounds InDesign pages and spreads.marginPreferences.pages.marginPreferences.bottom = 0. var myDocument = app.item(0). } //Create a new example document to demonstrate the change. myDocument.bottom = 0.masterSpreads. myDocument.item(0).pageWidth = "6p". var myX2 = right.marginPreferences){ //Save the current application default margin preferences. myDocument. //Set the application default margin preferences.left = 0.right = 0.masterSpreads.item(1).right = 0.marginPreferences.pages. with (app.right = 0.

pageWidth. previewBackgroundColor = UIColors.bottom)}).top}).documentPreferences.left}).marginPreferences. } Guides and grids Guides and grids make it easy to position objects on your document pages. {orientation:HorizontalOrVertical. guides.pages..pageHeight.or you can specify an array of RGB values //(with values from 0 to 255) //previewBackgroundColor = [192.CHAPTER 3: Documents Basic Page Layout 26 myDocument = app. From InDesign scripting.documentPreferences.) var myDocument = app. These are very useful items to add when you are creating templates for others to use.gray. <lb> location:(myPageWidth/2)}). {orientation:HorizontalOrVertical.. <lb> location:(myPageHeight/2)}). var myPageWidth = myDocument. {orientation:HorizontalOrVertical. 192.right)}). and visibility of guides. <lb> location:(myPageWidth .add(undefined. guides.add(undefined.add(). 192]. minimumSpaceAboveAndBelow = "12p". <lb> location:marginPreferences.vertical.documents. The following script fragment shows how to use guides.add(undefined. You can use scripting to change the layer. guides. you can control this using the fitToPage property. {orientation:HorizontalOrVertical. <lb> location:marginPreferences.. This property is ignored by vertical guides. just as you can from the user interface. {orientation:HorizontalOrVertical. guides.pasteboardPreferences){ //You can use either a number or a measurement string //to set the space above/below.documents. Defining guides Guides in InDesign give you an easy way to position objects on the pages of your document.add().item(0)){ //Place guides at the margins of the page. var myPageHeight = myDocument.add(undefined.add(undefined. //Place a guide at the horizontal center of the page.marginPreferences. {orientation:HorizontalOrVertical. <lb> location:(myPageHeight .. see Guides. with(myDocument. guides.horizontal. //You can set the preview background color to any of //the predefined UIColor enumerations. (For the complete script. } Horizontal guides can be limited to a given page or extend across all pages in a spread.horizontal. as shown in the following script fragment (from the GuideOptions tutorial script): . //Place a guide at the vertical center of the page. //.vertical.vertical. color.add(undefined.horizontal. with(myDocument. guides.

horizontalGridlineDivision = 14.spreads.right)}). {orientation:HorizontalOrVertical. } You also can create guides using the createGuides method on spreads and master spreads.add(undefined. myDocument. var myPageWidth = myDocument. with(myDocument. //Set up grid preferences.points. } Setting grid preferences To control the properties of the document and baseline grid. var myPageHeight = myDocument.add(undefined. 4.points.item(0)){ //Parameters (all optional): row count. <lb> location:(myPageWidth . {orientation:HorizontalOrVertical.verticalMeasurementUnits = MeasurementUnits. fit margins. guides.pages. <lb> location:(myPageHeight/2)}).bottom)}).horizontal.gray. {orientation:HorizontalOrVertical.documentPreferences.guide color.item(0)). //column gutter.top}).left}). UIColors. guides. row gutter.documents. with(myDocument.viewPreferences.viewPreferences. <lb> location:marginPreferences.gridPreferences){ baselineStart = 56. } . //Place a guide at the vertical center of the page.pageWidth.layers.add(undefined. you set the properties of the gridPreferences object. myDocument. as shown in the following script fragment (from the CreateGuides tutorial script): var myDocument = app. baselineShown = true. column count.vertical. <lb> location:(myPageWidth/2)}). horizontalGridSubdivision = 5 verticalGridlineDivision = 14. createGuides(4. guides.documents. guides.add(). "1p".marginPreferences. <lb> location:marginPreferences. layer. //Note that the createGuides method does not take an RGB array //for the guide color parameter.add(). true. verticalGridSubdivision = 5 documentGridShown = true.documents.add().horizontal. as shown in the following script fragment (from the DocumentAndBaselineGrid tutorial script): var myDocument = app.vertical. baselineDivision = 14.add(undefined. {orientation:HorizontalOrVertical. <lb> location:(myPageHeight . //Place a guide at the horizontal center of the page. "1p". remove existing. true.marginPreferences.horizontalMeasurementUnits = MeasurementUnits. //Set the document measurement units to points.CHAPTER 3: Documents Basic Page Layout 27 var myDocument = app. myDocument. {orientation:HorizontalOrVertical. {orientation:HorizontalOrVertical.horizontal. guides. with (myDocument.add(undefined. guides.pageHeight.documentPreferences.add(undefined.vertical.item(0)){ //Place guides at the margins of the page.

you can change the measurement units at the beginning of the script.points. horizontalMeasurementUnits = MeasurementUnits.5i” for 8.agates //* MeasurementUnits. They do this because you might be using a different measurement system when you run the script. the sample scripts used measurement strings.5 inches). verticalMeasurementUnits = MeasurementUnits. The following script fragment shows how to set guide and grid snap properties. } with(myDocument.) var myDocument = app. with(myDocument.viewPreferences){ //Measurement unit choices are: //* MeasurementUnits.guidePreferences){ guidesInBack = true.gridPreferences){ documentGridShown = false. guidesSnapTo = true.inches //* MeasurementUnits. use the document’s viewPreferences object. documentGridSnapTo = true. } If you are writing a script that needs to use a specific measurement system.CHAPTER 3: Documents Basic Page Layout 28 Snapping to guides and grids All snap settings for a document’s grids and guides are in the properties of the guidePreferences and gridPreferences objects. strings that force InDesign to use a specific measurement unit (for example.centimeters //* MeasurementUnits. baselineGridShown = true.activeDocument.activeDocument. //Objects "snap" to the baseline grid when //guidePreferences.ciceros //Set horizontal and vertical measurement units to points.millimeters //* MeasurementUnits. (For the complete script. with(myDocument.picas //* MeasurementUnits. This is shown in the following script fragment (from the ResetMeasurementUnits tutorial script): . guidesShown = true. } Changing measurement units and ruler Thus far.points //* MeasurementUnits.inchesDecimal //* MeasurementUnits. guidesLocked = false. then restore the original measurement units at the end of the script. see GuideGridPreferences. To specify the measurement system used in a script.points. as shown in the following script fragment (from the ViewPreferences tutorial script): var myDocument = app.guideSnapTo is set to true. “8.

activeDocument.points. verticalMeasurementUnits = MeasurementUnits. you can perform any series of script actions //that depend on the measurement units you've set. to get the margin //preferences from the active page.viewPreferences){ var myOldXUnits = horizontalMeasurementUnits. When you create a new document.add({name:"myDocumentPreset"}).activeDocument" with //"app. } //Set the application default measurement units to match the document //measurement units.viewPreferences. open a document that has the document set-up properties you want to use in the document preset. } catch (myError){ myDocumentPreset = app.points.viewPreferences){ try{ horizontalMeasurementUnits = myOldXUnits.activePage" in the following line (assuming the . try { var myPresetName = myDocumentPreset.viewPreferences.activeDocument with (myDocument.").documents. then run the following script (from the DocumentPresetByExample tutorial script): var myDocumentPreset.CHAPTER 3: Documents Basic Page Layout 29 var myDocument = app. Creating a preset by copying values To create a document preset using an existing document’s settings as an example.viewPreferences. //Fill in the properties of the document preset with the corresponding //properties of the active document. myDocumentPreset = app.item("myDocumentPreset"). //If the document preset "myDocumentPreset" does not already //exist.documentPresets.horizontalMeasurementUnits.documentPresets.viewPreferences. columns.name. } } Defining and applying document presets InDesign document presets enable you to store and apply common document set-up information (page size. page margins. horizontalMeasurementUnits = MeasurementUnits. create it. and bleed and slug areas).verticalMeasurementUnits. reset the measurement units to their original state. } //At this point.length > 0){ var myDocument = app. var myOldYUnits = verticalMeasurementUnits. app. if(app.horizontalMeasurementUnits = myDocument. app. } catch(myError){ alert("Could not reset custom measurement units. you can base the document on a document preset.verticalMeasurementUnits = myDocument.activeWindow. with (myDocument. At the end of //the script. with(myDocumentPreset){ //Note that the following gets the page margins //from the margin preferences of the document.replace "app. verticalMeasurementUnits = myOldYUnits.

activeDocument.documentPreferences. create it.documentBleedInsideOrLeftOffset.facingPages. documentBleedRight = app. right = "6p".activeDocument. left = "4p". left = myMarginPreferences. slugTopOffset = app.documentPreferences. documentBleedOutsideOrRightOffset. bottom = myMarginPreferences.documentPreferences.documentPreferences. documentBleedLeft = app.item("myDocumentPreset").activeDocument. right = myMarginPreferences. columnCount = myMarginPreferences. top = myMarginPreferences. myDocumentPreset = app.documentPreferences.documentPreferences.pageHeight.add({name:"myDocumentPreset"}).pageWidth.slugInsideOrLeftOffset.slugTopOffset. pageOrientation = app. try { var myPresetName = myDocumentPreset.activeDocument. slugInsideOrLeftOffset = app. slugBottomOffset = app.activeDocument.pageOrientation.pagesPerDocument.documentPreferences.documentPreferences.left.documentBleedTopOffset. var myMarginPreferences = app. facingPages = app.activeDocument.slugBottomOffset.activeDocument.columnGutter.documentPreferences.columnCount.activeDocument. slugRightOrOutsideOffset = app.documentPreferences.activeDocument.documentPresets. pageWidth = "7i".activeDocument. columnGutter = myMarginPreferences.activeDocument. documentBleedTop = app.activeDocument. } catch (myError){ myDocumentPreset = app.documentPreferences. } } Creating a document preset To create a document preset using explicit values.bottom.name.CHAPTER 3: Documents Basic Page Layout 30 //active window is a layout window). with(myDocumentPreset){ pageHeight = "9i". pageHeight = app.top. pagesPerDocument = app. . documentBleedBottom = app.activeDocument.documentBleedBottomOffset.marginPreferences. //If the document preset "myDocumentPreset" does not already exist. } //Fill in the properties of the document preset.documentPresets.slugRightOrOutsideOffset. run the following script (from the DocumentPreset tutorial script): var myDocumentPreset.activeDocument.documentPreferences. pageWidth = app.documentPreferences.right.

slugInsideOrLeftOffset = "3p". slugTopOffset = "3p". pageOrientation = PageOrientation. see MasterSpread.CHAPTER 3: Documents Basic Page Layout 31 top = "4p". insertionPoints. This is very important //--if you don't do this. pageOrientation = PageOrientation.add(). with(textFrames. slugRightOrOutsideOffset = "3p".viewPreferences. //Set up the document.documentPreferences){ pageHeight = "11i" pageWidth = "8. documentBleedBottom = "3p".5i" facingPages = true. } } //Set up the right page (recto).justification = Justification. with(pages. pagesPerDocument = 1. . documentBleedLeft = "3p".masterSpreads. myDocument.item(0)){ with(marginPreferences){ columnCount = 3. slugBottomOffset = "18p". The following script shows how to do that. (For the complete script.item(0).contents = SpecialCharacters. with(myDocument. "62p".emSpace. with(pages. bottom = "9p".item(0). getting objects to the correct position on the //page is much more difficult.contents = SpecialCharacters. with(myDocument. slug.item(0). documentBleedRight = "3p". and bleed.documents. } Setting up master spreads After setting up the basic document page size. documentBleedTop = "3p".add()){ geometricBounds = ["61p". insertionPoints.item(0)){ //Set up the left page (verso). } //Set the document's ruler origin to page origin. bottom = "6p" //"left" means inside. columnGutter = "1p". paragraphs. "right" means outside.portrait. columnCount = 1.autoPageNumber. facingPages = true.contents = SpecialCharacters.item(0). left = "6p" right = "4p" top = "4p" } //Add a simple footer with a section number and page number. "45p"].sectionMarker.pageOrigin.leftAlign. you probably will want to define the document’s master spreads.rulerOrigin = RulerOrigin. insertionPoints. "4p".) myDocument = app.item(1)){ with(marginPreferences){ columnCount = 3.portrait.

contents = SpecialCharacters. insertionPoints.justification = Justification.item(0). "47p"].item("B-Master"). and view metadata using the File Info dialog (choose File > File Info). see the XMP specification at http://partners. paragraphs.item(2) because JavaScript arrays are zero-based. see MetadataExample.contents = SpecialCharacters.autoPageNumber.pages.appliedMaster = app.item(0). (For the complete script. All this information is stored using XMP (Adobe Extensible Metadata Platform). insertionPoints. Adding XMP metadata Metadata is information that describes the content. left = "6p" right = "4p" top = "4p" } //Add a simple footer with a section number and page number.activeDocument. as shown in the following script fragment (from the ApplyMasterToMaster tutorial script): //Assumes that the active document has master spread named "B-Master" //that is not the same as the first master spread in the document.CHAPTER 3: Documents Basic Page Layout 32 columnGutter = "1p". you can create your own metadata container (email. you enter. "6p". bottom = "6p" //"left" means inside.) . In the InDesign user interface.pdf.item(0).item(0). an open standard for embedding metadata in a document. app. edit.com/asn/developer/pdf/MetadataFramework. "62p". All XMP properties for a document are in the document’s metadataPreferences object. origin.contents = SpecialCharacters.activeDocument.rightAlign.item(2).masterSpreads.item(0).masterSpreads.pages.item("B-Master"). in this example). insertionPoints. with(textFrames. To learn more about XMP. This example also shows that XMP information is extensible. author.add()){ geometricBounds = ["61p".appliedMaster = app. Use the same property to apply a master spread to a master spread page. "right" means outside.sectionMarker. or other attributes of a file. } } } To apply a master spread to a document page. app. use the appliedMaster property of the document page.item(0).adobe. The example below fills in the standard XMP data for a document. This metadata includes the document’s creation and modification dates. and other information.emSpace. copyright status.masterSpreads. You also can add XMP information to a document using InDesign scripting.activeDocument. If you need to attach metadata to a document and the data does not fall into a category provided by the metadata preferences object. as shown in the following script fragment (from the ApplyMaster tutorial script): //Assumes that the active document has a master page named "B-Master" //and at least three pages--page 3 is pages.activeDocument.

copyrightInfoURL = "http://www.documentPreferences. //Slug . myDocument.pageOrientation = PageOrientation.0/". copyrightNotice = "This document is copyrighted. keywords = ["animal". documentBleedInsideOrLeftOffset = "3p". description = "Example of xmp metadata scripting in InDesign CS".documentPreferences){ //Bleed documentBleedBottomOffset = "3p".adobe. see DocumentTemplate. var myX1 = left. "mineral". with (myDocument. "vegetable"].metadataPreferences){ author = "Adobe". } //Set up the bleed and slug areas. "email/*[1]". sets up master pages.add(). right = myX2. "someone@adobe.pageHeight = "9i". var myX2 = right. bottom = "74pt". //Document baseline grid will be based on 14 points. with (app. //Create a custom XMP container.pageWidth = "7i". documentBleedTopOffset = "3p".marginPreferences){ top = myY1. "email" var myNewContainer = createContainerItem("http://ns. format. documentTitle = "XMP Example".documentPreferences. documentBleedOutsideOrRightOffset = "3p". right = 14 * 5 + "pt".documents.documentPreferences. and //all margins are set in increments of 14 points. myDocument. myDocument.portrait. //At this point. top = 14 * 4 + "pt".". (For the complete script. and serverURL //properties that are automatically entered and maintained by InDesign.com").com". "email"). with(myDocument. var myY1 = top.adobe. //Set the application default margin preferences. defines slug and bleed areas. and adds job information to a table in the slug area. jobName = "XMP_Example_2003".com/xap/1.com/xap/1. left = myX1.0/". copyrightStatus = CopyrightStatus. adds information to the document’s XMP metadata. var myY2 = bottom. var myDocument = app.yes.add(). we can reset the application default margins to their original state. with (app. } //Make a new document.) //Set the application default margin preferences.documents.marginPreferences){ //Save the current application default margin preferences. setProperty("http://ns. adds page footers. //The metadata preferences object also includes the read-only //creator.CHAPTER 3: Documents Basic Page Layout 33 var myDocument = app. modificationDate. bottom = myY2.adobe. creationDate. } Creating a document template This example creates a new document. left = 14 * 4 + "pt".

name. slugTopOffset = "3p".name.name.item("Footer").name. } catch (myError){ myDocument.paragraphStyles.layers. } catch (myError){ myDocument. pointSize:11.item("Slug"). } catch (myError){ myDocument. try{ myDocument.CHAPTER 3: Documents Basic Page Layout 34 slugBottomOffset = "18p".paragraphStyles.characterStyles.layers.paragraphStyles. try{ myDocument. } myDocument.add({name:"footer_right". 80.item("PageNumberRed").paragraphStyles.item("footer_left"). } catch (myError){ myDocument.layers.rightAlign.colors. pointSize:11.add({name:"footer_left". } catch (myError){ myDocument.add({name:"PageNumberRed".colors.add({name:"GuideLayer"}).item("PageNumberRed"). } //Create a layer for the footer items.colors. colorValue:[20. } catch (myError){ myDocument. try{ myDocument. leading:14}).layers. slugRightOrOutsideOffset = "3p". slugInsideOrLeftOffset = "3p". set up some default styles. //Create up a pair of paragraph styles for the page footer text.add({name:"page_number"}).layers.add({name:"Footer"}).process.name. } //Create a color. .item("footer_right"). try{ myDocument.name. 100. //These styles have only basic formatting. try{ myDocument. } //Next. justification:Justification.paragraphStyles.characterStyles.item("GuideLayer"). try{ myDocument.item("footer_left").name.layers.characterStyles. 10]}). basedOn:myDocument.item("page_number"). try{ myDocument. } //Create a layer for guides.item("page_number"). model:ColorModel. } //Create up a pair of paragraph styles for the page footer text. } catch (myError){ myDocument.fillColor = myDocument. //Create up a character style for the page numbers. } //Create a layer for the slug items. leading:14}).add({name:"Slug"}).

} //Document XMP information.layers.horizontal.horizontal.item(0)){ //Left and right are reversed for left-hand pages (becoming "inside" and "outside"-//this is also true in the InDesign user interface).bottom.documentPreferences. location:myBottomMargin + 14. jobName = "7 x 9 book layout template".viewPreferences){ rulerOrigin = RulerOrigin.points. {orientation:HorizontalOrVertical. .item(0)){ with(pages. horizontalMeasurementUnits = MeasurementUnits. var myRightMargin = myDocument.add(myDocument.layers.layers. documentTitle = "Example".adobe. {orientation:HorizontalOrVertical.vertical.layers. "book".0/". keywords = ["7 x 9".adobe. verticalGridSubdivision = 5 documentGridShown = false. guides.layers. guides.no.add(myDocument.top.name. verticalMeasurementUnits = MeasurementUnits. } //Document baseline grid and document grid with(myDocument. location:myBottomMargin.masterSpreads.item("GuideLayer"). copyrightNotice = "This document is not copyrighted.pageHeight marginPreferences.location:marginPreferences. baselineDivision = 14.CHAPTER 3: Documents Basic Page Layout 35 } //Create a layer for the body text.documentPreferences. guides.horizontal.right}). fitToPage:false}). "template"].pageWidth marginPreferences. guides.item("GuideLayer").left. guides. "email/*[1]".item("GuideLayer"). try{ myDocument.points. copyrightStatus = CopyrightStatus.add(myDocument.adobe.add(myDocument. {orientation:HorizontalOrVertical.com/xap/1. var myBottomMargin = myDocument.com/xap/1.com"). location:myRightMargin}). with (myDocument. } //Set up the master spread.add(myDocument.layers. fitToPage:false}). } with(myDocument.". with(myDocument.item("GuideLayer").add({name:"BodyText"}). horizontalGridSubdivision = 5 verticalGridlineDivision = 14. } catch (myError){ myDocument. horizontalGridlineDivision = 14. {orientation:HorizontalOrVertical.metadataPreferences){ author = "Olav Martin Kvern".layers. baselineShown = false. {orientation:HorizontalOrVertical. var myNewContainer = createContainerItem("http://ns. "email"). "okvern@adobe. location:marginPreferences. copyrightInfoURL = "http://www.gridPreferences){ baselineStart = 56.pageOrigin. setProperty("http://ns. description = "Example 7 x 9 book layout".com".0/".vertical.item("GuideLayer").item("BodyText").

myLeftFooter.horizontal.documentPreferences. myRightFooter. fitToPage:false}).characterStyles.characters.parentStory.layers. //Slug information.item(0).tables.item("BodyText"). myLeftFooter.bottom.item("GuideLayer").pageHeight + 144. contents:myString}).item(0).appliedCharacterStyle = myDocument.parentStory.contents = SpecialCharacters. var myLeftFrame = textFrames.add(myDocument.add(myDocument. myRightFooter. false)). } with(pages. undefined.item("Slug"). location:myRightMargin}). guides. location:myBottomMargin + 28.ite m("footer_left".add(myDocument.right.right. var myRightMargin = myDocument.left}).insertionPoints.documentPreferences.left. undefined. //Body text master text frame. marginPreferences. myLeftFooter.contents = SpecialCharacters. marginPreferences. guides.emSpace.parentStory.add(myDocument. "email/*[1]").item("Footer").item("GuideLayer").add(myDocument.contents = SpecialCharacters.top. var myRightSlug = textFrames.parentStory.add().insertionPoints.pageWidth marginPreferences. myRightMargin]}) myRightFooter.item(0).item(0).paragraphStyles. myBottomMargin+28. undefined. } var myLeftSlug = textFrames. undefined.autoPageNumber.item(0).add(myDocument.item(0). myRightFooter.CHAPTER 3: Documents Basic Page Layout 36 fitToPage:false}). false)).metadataPreferences){ var myString = "Author:\t" + author + "\tDescription:\t" + description + "\rCreation Date:\t" + new Date + "\tEmail Contact\t" + getProperty("http://ns.layers.item(0).layers.parentStory.item(0).item(1)){ var myBottomMargin = myDocument.pageHeight+36. myDocument.location:marginPreferences.item("Footer"). guides.pageHeight marginPreferences. {geometricBounds:[myBottomMargin+14. {geometricBounds:[marginPreferences. {geometricBounds:[myBottomMargin+14. {orientation:HorizontalOrVertical.item("page_number"). undefined. undefined. myLeftSlug. myLeftFooter.paragraphs.parentStory.item("page_number").0/".insertionPoints.insertionPoints. marginPreferences.contents = SpecialCharacters.layers. .adobe.it em("footer_right". var myLeftFooter = textFrames. {orientation:HorizontalOrVertical.contents = SpecialCharacters.item(-1).add(myDocument.characterStyles. undefined.emSpace.add(myDocument.layers.com/xap/1.item(0). {geometricBounds:[myDocument. myRightMargin].contents = SpecialCharacters.parentStory. myRightMargin]}) myLeftFooter.documentPreferences. myBottomMargin. marginPreferences.parentStory. myBottomMargin+28.parentStory.right. //Slug information.sectionMarker.vertical.appliedCharacterStyle = myDocument. undefined.right.item("Slug").characters.autoPageNumber. undefined.applyStyle(myDocument.layers.sectionMarker.parentStory.vertical.paragraphs.paragraphStyles. myRightMargin]}).layers. with(myDocument. myRightFooter.documentPreferences. var myRightFooter = textFrames.insertionPoints.insertionPoints.applyStyle(myDocument.parentStory.item("GuideLayer").layers. {orientation:HorizontalOrVertical.

watermarkPreferences. app. app. are applied to the document watermark preferences for each new document created by InDesign. myDocument.watermarkVCenter.parentStory. undefined. .watermarkDrawInBack = true.watermarkFontPointSize = 72.watermarkPreferences. app.watermarkPreferences. app.watermarkPreferences.watermarkFontColor = UIColors.red. no user interface component exists in InDesign for managing watermarks.watermarkDoPrint = true.item(0). undefined). app.watermarkFontFamily = "Arial".watermarkRotation = -45.watermarkHorizontalPosition = WatermarkHorizontalPositionEnum. (For the complete script for setting application preferences. marginPreferences.left.watermarkVerticalOffset = 0. //Body text master text frame.watermarkPreferences.watermarkOpacity = 60.left.watermarkPreferences. myRightMargin]. This setting has no effect on existing documents. app.select(NothingEnum. contents:myString}).watermarkVisibility = true. app. The same group of watermark preferences exist for both the document and the application objects. myRightMargin].item("BodyText").watermarkPreferences. Creating watermarks You can apply watermarks to documents in InDesign or InDesign Server using scripting. Setting or changing a document’s watermark preferences replaces any previous watermark settings for the document. var myRightFrame = textFrames.add(myDocument.pageHeight + 144.marker = "Section 1".layers. undefined. Document-level watermark preferences apply only to that document.watermarkPreferences. app.watermarkPreferences.watermarkText = "Confidential". myRightSlug. Currently. {geometricBounds:[marginPreferences. //When you link the master page text frames. previousTextFrame:myLeftFrame}).watermarkPreferences. app.sections.watermarkVerticalPosition = WatermarkVerticalPositionEnum. marginPreferences. one of the frames sometimes becomes selected.watermarkPreferences. app. app.documentPreferences. Deselect it. app.tables. Setting watermark preferences The following script fragment shows how to set watermarks at the application level.pageHeight+36.watermarkHCenter. app. A document’s watermark preferences can be set in two ways using scripting: Application-level watermark preferences. A watermark will be applied to all documents created after this code finishes.documentPreferences. Both the document and application watermark preference settings persist after the document or application is closed until a script changes them. {geometricBounds:[myDocument.watermarkPreferences.nothing.watermarkPreferences. app.watermarkHorizontalOffset = 0.watermarkFontStyle = "Bold". } } //Add section marker text--this text will appear in the footer.watermarkPreferences.top.CHAPTER 3: Documents Basic Page Layout 37 undefined. myBottomMargin. see ApplicationWatermark. myDocument.) app. if any are set.add().

watermarkHorizontalOffset = 0. myDocument.item(-1).watermarkPreferences. you must select the page.watermarkDrawInBack = true. myDocument. myDocument.watermarkFontFamily = "Arial". myDocument.documents. myDocument. InDesign CS5 removes this limitation and allows different page sizes within a single InDesign document.item(2). myDocument. myDocument. myDocument.documents. app. InDesign no longer turns on the watermark settings for new documents by default.watermarkPreferences. you do this using the Page Tool on the Tools Panel. you can still set watermarks for individual documents. You can also select a page using scripting. app.ADD_TO). myPages.watermarkText = "Confidential".blue.ADD_TO). 2. //Select page 1 and 2.select(SelectionOptions. .watermarkPreferences.item(0).watermarkVCenter.watermarkHCenter.select().watermarkPreferences.activeDocument. as shown in the following script fragment.watermarkPreferences. The following script shows how. You can turn off watermarks in an individual document at any time.watermarkDoPrint = true.watermarkPreferences. Adjusting Page Sizes and Layout Prior to InDesign CS5.watermarkHorizontalPosition = WatermarkHorizontalPositionEnum. The following script fragment shows how to turn off application-level watermarks. see DocumentWatermark. In the InDesign user interface. Disabling watermarks After turning off the application setting for watermarks. //Select last page. see “Defining page size and document length”.watermarkPreferences.watermarkPreferences.item(0). myDocument.watermarkPreferences.watermarkPreferences. rather than to the application. However.. You can also apply geometric transformations to individual pages.watermarkPreferences.watermarkFontColor = UIColors. pages in a document were limited to a single page size. myDocument. myDocument.watermarkVerticalPosition = WatermarkVerticalPositionEnum.watermarkPreferences.watermarkVisibility = false.watermarkPreferences.watermarkFontPointSize = 72. myDocument. 1. (For the complete script for setting document preferences.watermarkPreferences.pages. myDocument. var myDocument = app.select(myPages.watermarkOpacity = 60.watermarkPreferences.) var myDocument = app.watermarkVisibility = false.watermarkVerticalOffset = 0.CHAPTER 3: Documents Adjusting Page Sizes and Layout 38 The same preferences can be applied to a document object by referring to a document..watermarkVisibility = true. Selecting pages Before changing a page’s size or applying a transformation to the page.watermarkRotation = -45. 3).) //Given a document with four pages (0. (For the complete script. var myPages = myDocument.item(1).watermarkPreferences. SelectionOptions. see PageSelect. myPages. myDocument. myDocument. For information on setting the default page size.watermarkFontStyle = "Bold".

. so reframing can be used to change a page’s size by making the bounding box larger or smaller.item(2). //Resize page to 400 points width and 600 points height. myPage. Prior to InDesign CS5. The following script shows how to change a page’s size using the resize method. var myPages = myDocument. //Make the page one inch wider and one inch higher. Reframing changes the bounding box of a page.reframe(CoordinateSpaces.REPLACING_CURRENT_DIMENSIONS_WITH..MULTIPLYING_CURRENT_DIMENSIONS_BY. 2]).) . Transforming pages Operations that change the geometry of objects are called transformations. myPages. myY1]. 1. var myPages = myDocument.) //Given a document with four pages (0. see PageResize.pages. 2. var myX1 = myBounds[1]. refer to “Transforming Page Items”. [[myX1. the transform method could rotate. shear. scale. 2. [2. ResizeMethods. The following script shows how to change a page’s size using the reframe method. var myX2 = myBounds[3]+72.CENTER_ANCHOR. (For the complete script.pages. you can also apply the resize and reframe operations to pages to change their sizes. The following script shows how to transform a page with scripting. In InDesign CS5. var myPage = myPages. To transform a page: 1. 2. var myDocument = app.INNER_COORDINATES. 3). Create a transformation matrix.item(1). myY2]]).CENTER_ANCHOR. For technical details about transformation architecture. AnchorPoint.) //Given a document with four pages (0. the transform method can also be used on pages. ResizeMethods.resize(CoordinateSpaces.activeDocument.resize(CoordinateSpaces. [400. see PageTransform. AnchorPoint.INNER_COORDINATES.INNER_COORDINATES. Apply the transformation matrix to the page using the transform method. 1. NOTE: Your minimum page size is determined by the page’s margins.. //Resize page to two times bigger myPages. see PageReframe. See “Setting page margins and columns” for more information. and move (translate) page items on a page. (For the complete script.CHAPTER 3: Documents Adjusting Page Sizes and Layout 39 Resizing and reframing pages You can resize or reframe page items on a page by scripting. var myBounds = myPage.activeDocument. 600])..bounds. var myY1 = myBounds[0]. var myDocument = app. var myY2 = myBounds[2]+72. (For the complete script. 3). [myX2.item(1). With InDesign CS5.

This is called the Master Page Overlay. var myRotateMatrix = app.transform(CoordinateSpaces.masterPageTransform = myTranslateMatrix. var myDocument = app. In addition to tracking which master is applied. var myScaleMatrix = app. myPages. 3). var myDocument = app. var myShearMatrix =app.item(2).transformationMatrices.transformationMatrices. pages now also maintain a matrix that determines how the master page draws on the page.transformationMatrices. When you select a page using the Page Tool on the Tools Panel. you can do more by scripting.. myTransformationMatrix).PASTEBOARD_COORDINATES.transformationMatrices.item(3). //Rotate a page around its center point.5}). The following script shows how to transform a master page overlay. var myPages = myDocument. 2.add({clockwiseShearAngle:30}).masterPageTransform = myShearMatrix. verticalScaleFactor:0.8}).masterPageTransform = myRotateMatrix. verticalScaleFactor:0. //Scale master page overlay around its top-left corner.transformationMatrices. myPages. 2. myTransform(myPages. 3).activeDocument.item(0). You can move the overlay around with the mouse. function myTransform(myPage. myRotateMatrix).item(1). //Rotate master page overlay around its top-left corner. //Shear master page overlay around its top-left corner. //Scale a page around its center point.pages.CHAPTER 3: Documents Adjusting Page Sizes and Layout 40 //Given a document with four pages (0.. var myScaleMatrix = app. myPages. 1. Although the user interface allows only translation (moving x and y). (For the complete script.pages. //Translate master page overlay 1 inch right and 2 inches down.) //Given a document with four pages (0..add({horizontalScaleFactor:0.item(1).add({horizontalTranslation:72. var myShearMatrix = app.add({clockwiseShearAngle:30}).add({horizontalScaleFactor:0. var myPages = myDocument.8.add({counterclockwiseRotationAngle:27}). myScaleMatrix). it is possible for a page and its master page to be different sizes. myTransform(myPages. //Shear a page around its center point.transformationMatrices. AnchorPoint..activeDocument.5. myPages.item(0). var myRotateMatrix = app. verticalTranslation:144}). .add({counterclockwiseRotationAngle:27}). 1. myTransform(myPages.CENTER_ANCHOR. myTransformationMatrix) { myPage. myShearMatrix).masterPageTransform = myScaleMatrix.item(2).transformationMatrices. you can see how the master page is positioned by checking the Show Master Page Overlay checkbox on the control panel. see MasterPageTransform. } Master page overlay Because pages can have multiple sizes. InDesign achieves this by applying a transform to the master overlay matrix. var myTranslateMatrix = app.

//ppd = "AGFA-SelectSet5000SF". printer can be //either a string (the name of the printer) or Printer. Setting print preferences The print preferences object contains properties corresponding to the options in the panels of the Print dialog. printMasterPages = false. then the collating //property is unavailable. see PrintDocument. set the pageRange property of the document’s print preferences object before printing. with(app.postscript file. then //the printFile property contains the file path to the output file.postscript file.ps". not the page index).activeDocument.) //PrintPreferences.CHAPTER 3: Documents Printing a Document 41 Printing a Document The following script prints the active document using the current print preferences.postScript file. the copies //property is unavailable.) app.printPreferences. see PrintPreferences. reverseOrder = false.pageRange = "22" app.allPages or a page range string.activeDocument.e. //printer = "AGFA-SelectSet 5000SF v2013.allPages or a page range string. //The page range can be either PageRange.activeDocument. printSpreads = false. activePrinterPreset is ignored in this //example--we'll set our own print preferences. that it contains a page named "22".print().postscriptFile. //Here's an example of setting the printer to a specific printer. //If the printer property is set to Printer. Printing using page ranges To specify a page range to print. //copies = 1. (For the complete script. as shown in the following script fragment (from the PrintPageRange tutorial script): //Prints a page range from the active document. //Assumes that you have a document open. app. //If the printer property is the name of a printer. //A page number entered in the page range must correspond to a page //name in the document (i.printPreferences){ //Properties corresponding to the controls in the General panel //of the Print dialog box. printer = Printer.activeDocument. .108". then the ppd property //is locked (and will return an error if you try to set it). //If the printer property is set to Printer. Attempting to set it will generate an error.print(false). This following script shows how to set print preferences using scripting.postscriptFile. //printFile = "/c/test. //If the printer property is set to Printer. If the page name is //not found.allPages. pageRange = PageRange. Attempting to set it will generate an error. //pageRange can be either PageRange. InDesign will display an error message. or if the //selected printer does not support collation. //collating = false.. (For the complete script.jsx //An InDesign CS5 JavaScript //Sets the print preferences of the active document.

printNonprinting = false.separations. . //blackFrequency = 175.off){ printBlack = true. //yellowAngle = 0. printGuidesGrids = false. attempting to set the following //properties will generate an error. //cyanFrequency = 175. flip = Flip.all. //yellowFrequency = 175. //If trapping is on.custom. //-----------------------------------------------------------------------//negative = true.CHAPTER 3: Documents Printing a Document 42 sequence = Sequences. //paperWidth = 1200. //magentaAngle = 75. printCyan = true. //Note the lowercase "i" in "Builtin" trapping = Trapping. //simulateOverprint = false. //The following properties are not needed (because //colorOutput is set to separations). //magentaFreqency = 175.off){ printBlankPages = false. //Page width and height are ignored if paperSize is not PaperSizes. } } catch(myError){} //Only change the ink angle and frequency when you want to override the //screening set by the screening specified by the screening property.custom. //compositeFrequency = 175. //-----------------------------------------------------------------------try{ paperSize = PaperSizes. try{ if(trapping == Trapping.portrait. } catch(myError){} //If trapping is on. //compositeAngle = 45. } } catch(myError){} //-----------------------------------------------------------------------//Properties corresponding to the controls in the //Setup panel of the Print dialog box.applicationBuiltin. try{ colorOutput = ColorOutputModes. printMagenta = true. //paperHeight = 1200. printPageOrientation = PrintPageOrientation. trying to set the colorOutput //parameter will result in an error. //If a device independent PPD is specified. //-----------------------------------------------------------------------//Properties corresponding to the controls in the //Output panel of the Print dialog box.none. //blackAngle = 45. setting the following properties will produce an error. //cyanAngle = 15. try{ if(trapping == Trapping. printYellow = true.

//If any bleed area is greater than zero. tile = false. if(bleedBottom == 0 && bleedTop == 0 && bleedInside == 0 && bleedOutside == 0){ bleedMarks = true.activeDocument. //markType = MarkTypes. //The following properties are not needed because tile is set to false. //Get the bleed amounts from the document's bleed and add a bit. bleedTop = app. cropMarks = true. } } catch(myError){} //-----------------------------------------------------------------------//Properties corresponding to the controls in the Marks and Bleed //panel of the Print dialog box. documentBleedBottomOffset+3.documentPreferences.auto. //The following properties is not needed because //thumbnails is set to false. then export the bleed marks. //allPrinterMarks = true. try{ if(trapping == Trapping. scaleProportional = true. } colorBars = true. //tilingType = TilingTypes.documentPreferences. documentBleedInsideOrLeftOffset+3. includeSlugToPrint = false.scaleWidthHeight.documentPreferences. //tilingOverlap = 12.documentBleedTopOffset+3. bleedBottom = app. paperGap = 0.activeDocument. scaleHeight = 100. scaleMode = ScaleModes. thumbnails = false.off){ textAsBlack = false. paperOffset = 0.centered. scaleWidth = 100.CHAPTER 3: Documents Printing a Document 43 pagePosition = PagePositions. //thumbnailsPerPage = 4. paperTransverse = false.p125pt markOffset = 6. } catch(myError){} //If trapping is on. documentBleedOutsideOrRightOffset+3. registrationMarks = true. } else{ bleedMarks = false. //If useDocumentBleedToPrint = false then setting //any of the bleed properties //will result in an error. markLineWeight = MarkLineWeight. bleedInside = app. attempting to set the //following properties will produce an error.default. useDocumentBleedToPrint = false.activeDocument. .documentPreferences. bleedOutside = app.activeDocument. //-----------------------------------------------------------------------//Set the following property to true to print all printer's marks. pageInformationMarks = true.

//attempting to set the following properties will return an error.level3. . trying to set the graphics //send data will result in an error. //-----------------------------------------------------------------------//If a device independent PPD is specified. } catch(e){} //-----------------------------------------------------------------------//Properties corresponding to the controls in the Color Management //panel of the Print dialog box. } catch(e){} try{ postScriptLevel = PostScriptLevels.useColorSettings.useDocument. omitEPS = false. omitBitmaps = false. } catch(myError){} fontDownloading = FontDownloading. //-----------------------------------------------------------------------opiImageReplacement = false. try{ sourceSpace = SourceSpaces.useDocument. //The following line assumes that you have a flattener //preset named "high quality flattener".binary. profile = Profile. try{ dataFormat = DataFormat.allImageData. downloadPPDFOnts = true. intent = RenderingIntent.colorSettings is false. } catch(e){} //-----------------------------------------------------------------------//Properties corresponding to the controls in the Advanced //panel of the Print dialog box. try{ flattenerPresetName = "high quality flattener". crd = ColorRenderingDictionary. } Printing with printer presets To print a document using a printer preset. Exporting a Document as PDF InDesign scripting offers full control over the creation of PDF files from your page-layout documents. try{ sendImageData = ImageDataTypes.complete. //-----------------------------------------------------------------------//If the useColorManagement property of app. include the printer preset in the print command. } catch(e){} ignoreSpreadOverrides = false.CHAPTER 3: Documents Exporting a Document as PDF 44 //-----------------------------------------------------------------------//Properties corresponding to the controls in the //Graphics panel of the Print dialog box. omitPDF = false.postscriptCMS.

) var myPDFExportPreset = app.item("prepress").exportFile(ExportFormat. File("/c/myTestDocument.) app. //colorBitmapSamplingDPI is not needed when colorBitmapSampling //is set to none. includeStructure = false. using the current PDF export options. File("/c/myTestDocument. (For the complete script. try{ ignoreSpreadOverrides = false.pdfType.activeDocument.acrobat6.activeDocument. //Setting subsetFontsBelow to zero disallows font subsetting. subsetFontsBelow = 0. acrobatCompatibility = AcrobatCompatibility.zip. false. colorBitmapCompression = BitmapCompression.CHAPTER 3: Documents Exporting a Document as PDF 45 Exporting to PDF The following script exports the current document as PDF.pdf"). see ExportPDFWithOptions. includeHyperlinks = true. Setting PDF export options The following script sets the PDF export options before exporting. //thresholdToCompressGray is not needed in this example. includeICCProfiles = true.allPages. pageRange = PageRange. see ExportPDF. generateThumbnails = false. } catch(e){} includeBookmarks = true. grayscaleBitmapSampling = Sampling.eightBit.none. The following script fragment shows how to export to PDF using a PDF export preset. //set subsetFontsBelow to some other value to use font subsetting. .zip.) with(app.pdf"). interactiveElementsOption = InteractiveElementsOptions. grayscaleBitmapCompression = BitmapCompression. exportNonPrintingObjects = false. app. // //Bitmap compression/sampling/quality options. myPDFExportPreset). (For the complete script.doNotInclude. colorBitmapQuality = CompressionQuality. //grayscaleBitmapSamplingDPI is not needed when grayscaleBitmapSampling //is set to none. monochromeBitmapSampling = Sampling.pdfExportPresets.pdfType. exportLayers = false. colorBitmapSampling = Sampling. //thresholdToCompressColor is not needed in this example. monochromeBitmapCompression = BitmapCompression. includeSlugWithPDF = false.none.none.pdfExportPreferences){ //Basic PDF output options. false). grayscaleBitmapQuality = CompressionQuality. see ExportPDFWithPreset. exportReaderSpreads = false.zip.eightBit. (For the complete script. exportGuidesAndGrids = false.exportFile(ExportFormat.

pdfMarkType = 1147563124.activeDocument.) . // //Printers marks and prepress options. bleedBottom = app. //monochromeBitmapSamplingDPI is not needed when //monochromeBitmapSampling is set to none. false).CHAPTER 3: Documents Exporting a Document as PDF 46 //thresholdToCompressMonochrome is not needed in this example.pdfType. //Set viewPDF to true to open the PDF in Acrobat or Adobe Reader.documentPreferences. } //Now export the document. app. //Get the bleed amounts from the document's bleed. compressTextAndLineArt = true.activeDocument. printerMarkWeight = PDFMarkWeight.documentPreferences. colorTileSize = 128. //Default mark type.activeDocument. documentBleedInsideOrLeftOffset. grayTileSize = 128. then export the bleed marks.unchangedColorSpace. cropMarks = true.documentBleedTopOffset.compressNone. if(bleedBottom == 0 && bleedTop == 0 && bleedInside == 0 && bleedOutside == 0){ bleedMarks = true. cropImagesToFrames = true. pdfColorSpace = PDFColorSpace.pdf").p125pt. documentBleedBottomOffset. } colorBars = true. documentBleedOutsideOrRightOffset. try{ simulateOverprint = false. omitEPS = false. compressionType = PDFCompressionType.documentPreferences. bleedInside = app. pageInformationMarks = true.activeDocument. pageMarksOffset = 12. (For the complete script. bleedOutside = app. omitPDF = false.documentPreferences.activeDocument. see ExportPageRangeAsPDF. } catch(e){} useDocumentBleedWithPDF = true. optimizePDF = true. viewPDF = false. // //Other compression options. } else{ bleedMarks = false. File("/c/myTestDocument. You'll have to fill in your own file path. omitBitmaps = false. registrationMarks = true. Exporting a range of pages to PDF The following script shows how to export a specified page range as PDF. //If any bleed area is greater than zero.exportFile(ExportFormat. bleedTop = app.

) //Display a "choose folder" dialog box. myFile.pdf". //If the page name contains a colon (as it will if the //document contains sections). //The name of the exported files will be the base name + the //page name + ". see ExportEachPageAsPDF. } var myPDFExportPreset = app.name.add(). File("/c/myTestDocument.exportFile(ExportFormat.allPages or a page range string //(just as you would enter it in the Print or Export PDF dialog box).item(myCounter)."gi")."). Exporting individual pages to PDF The following script exports each page from a document as an individual PDF file.replace(myRegExp. } } else{ alert("Please open a document and try again. myFile = new File(myFilePath).destroy().documents. } var myResult = myDialog. 3-6. if(app. 12".pdfExportPreferences.pdf").dialogs. if(myResult == true){ var myBaseName = myBaseNameField. var myDocument = app.item("prepress") app. (For the complete script. myFilePath.selectDialog ("Choose a Folder").editContents. "_"). minWidth:160}). pageRange = "1. } function myExportPages(myFolder){ var myPageName. myCounter < myDocument.CHAPTER 3: Documents Exporting a Document as PDF 47 with(app.show({name:"ExportPages"}). var myBaseNameField = textEditboxes.activeDocument.exportFile(ExportFormat. myDocument. for(var myCounter = 0.dialogColumns. 7.pdfType. var myDialog = app. //then remove the colon. app. myPDFExportPreset).pages. var myDocumentName = myDocument. //Remove the dialog box from memory.pdfType. with(myDialog.destroy().length != 0){ var myFolder = Folder.pageRange = myPageName. } } .pages.length.pdfExportPresets.add(). false. var myRegExp = new RegExp(":".add({editContents:myDocumentName. } } else{ myDialog.activeDocument. 9-11.pdf".dialogRows.pdfExportPreferences){ //pageRange can be either PageRange. myFile.add()){ staticTexts.add({staticLabel:"Base name:"}). myPageName = myPageName. if(myFolder != null){ myExportPages(myFolder). myDialog. false).name. myFilePath = myFolder + "/" + myBaseName + "_" + myPageName + ". myCounter++){ myPageName = myDocument.

If you export more than a single page. see ExportAsEPS. before exporting.pageRange = "1-3. myCounter < myDocument. Exporting Pages as EPS When you export a document as EPS.exportFile(ExportFormat. var myFile = new File("/c/myTestFile. myDocument. 9".wipeTransition.. //Note that the page name is not necessarily the index of the page in the //document (e. The index of the page in the document is not necessarily the name of the page (as defined by the section options for the section containing the page). for(var myCounter = 0.spreads. app. app. . 6.openInFullScreen = true.pageTransitionDirection = PageTransitionDirectionOptions. myFile. by definition.exportFile(ExportFormat.exportFile(ExportFormat. myFile.epsType. app. the first page of a document whose page numbering starts //with page 21 will be "21".pageTransitionDuration = PageTransitionDurationOptions.item(myCounter).item(myCounter). false).flipPagesSpeed = 5. app. see ExportPageRangeAsEPS.interactivePDFExportPreferences.interactivePDFInteractiveElementsOption = InteractivePDFInteractiveElementsOptions. Exporting a range of pages to EPS To control which pages are exported as EPS. false).. (For the complete script.spreads.desktop + "/InteractivePDF.) //Enter the name of the page you want to export in the following line. can contain only a single page).epsExportPreferences.interactivePDFExportPreferences. //Export the document to PDF. InDesign appends the index of the page to the filename.activeDocument. myDocument. InDesign saves each page of the file as a separate EPS graphic (an EPS..epsType.interactivePDFExportPreferences. } app. set the page range property of the EPS export preferences to a page-range string containing the page or pages you want to export. not 1). (For the complete script.pageTransitionType PageTransitionTypeOptions.eps").activeDocument. app.interactivePDFExportPreferences. app.length.includeAllMedia.medium.down.interactivePDF. Exporting all pages to EPS The following script exports the pages of the active document to one or more EPS files. (For the complete script.) var myFile = new File("/c/myTestFile.pdf"). myDocument.item(myCounter).File(Folder.flipPages = true.eps"). myCounter++){ myDocument.) //Given a document "myDocument.g." add page transitions.spreads.spreads.CHAPTER 3: Documents Exporting Pages as EPS 48 Exporting PDF with Interactive Features The following script shows how to export a document with interactive features as a PDF. see ExportInteractivePDF. false).

myPageName. //page name.eps". var myDialog = app.pages. //Generate a file path from the folder name.add().length.epsType. } } .) //Display a "choose folder" dialog box. //then remove the colon.dialogs. myDialog. minWidth:160}). app. if(myFolder != null){ myExportPages(myFolder). app. var myDocumentName = myDocument. "_"). but it offers more control over file naming than the earlier example. var myDocument = app. if(app.name. myFilePath = myFolder + "/" + myBaseName + "_" + myPageName + ".item(myCounter).show().pageRange = myPageName. with(myDialog. myPageName = myPageName.destroy().add({editContents:myDocumentName.length != 0){ var myFolder = Folder. } } else{ myDialog. var myBaseName = myBaseNameField. } var myResult = myDialog.dialogColumns. if(myResult == true){ //The name of the exported files will be the base name + //the page name + ".eps".pages. for(var myCounter = 0. myCounter++){ myPageName = myDocument. } function myExportPages(myFolder){ var myFilePath. myFile. //If the page name contains a colon (as it will if the //document contains sections). myCounter < myDocument. //Remove the dialog box from memory.activeDocument.documents.editContents. myFile = new File(myFilePath).activeDocument.add({name:"ExportPages"}).eps". } } else{ alert("Please open a document and try again. false). myFile.selectDialog ("Choose a Folder")."gi").name. (For the complete script. //The name of the exported files will be the base name + //the page name + ".destroy(). var myRegExp = new RegExp(":".replace(myRegExp.epsExportPreferences.add({staticLabel:"Base name:"}).add()){ staticTexts.exportFile(ExportFormat.dialogRows. var myBaseNameField = textEditboxes. see ExportEachPageAsEPS. the base document name.").CHAPTER 3: Documents Exporting Pages as EPS 49 Exporting as EPS with file naming The following script exports each page as an EPS.

the allPageItems collection is a flattened collection of all page items assigned to the layer. You also can use layers as an organizational tool. It uses the JavaScript form of the object names. The basic properties of a layer are shown in the column at the left of the figure.g. it will not appear in the pageItems collection. in addition to finding it inside a layer object). You can think of layers as transparent planes stacked on top of each other. If a page item is inside a group. or spread. for example. regardless of their location in the object hierarchy. This chapter covers scripting techniques related to layers in an InDesign layout and discusses common operations involving layers. you can get a reference to a text-frame object from a story. It is important to note the distinction between the page-items collection and the allPageItems collection.. text object.4 Working with Layers InDesign’s layers are the key to controlling the stacking order of objects in your layout. Understanding the Layer Object Model The following figure shows the layer object model. however. 50 . Note the following about the diagram: It focuses on the location of a layer and its contents in the context of the object hierarchy of a document. A page item inside a group on the layer would appear in the allPageItems collection. page. The former is a collection containing only the top-level page items in a layer. it does not attempt to show all the other ways a script might work with the content of a layer (e. A document can contain one or more layers. the object hierarchy is the same in all scripting languages. at the right. Similarly. Layers are document wide. and each document includes at least one layer. the allGraphics property contains all graphics stored in page items assigned to the layer. not bound to specific pages or spreads. In contrast. regardless of their location in the object hierarchy. the objects that may be contained by the layer object. putting one type of content on a given layer or set of layers.

When you create a new layer. You also can change the layer to which a selected page item is assigned by dragging and dropping the layer proxy in the Layers panel. This section describes the most common ways to refer to layers.) This section shows how to accomplish these tasks using InDesign scripting. and merge layers using the Layers panel. Creating layers The following script fragment shows how to create a new layer. the layer appears above all other layers in the document. see the InDesign online help.layers. (For the complete script.add().CHAPTER 4: Working with Layers Scripting Layers 51 Scripting Layers In InDesign’s user interface. see AddLayer. . delete. Referring to layers InDesign scripting offers several ways to refer to a layer object.) //Given a document "myDocument". var myLayer = myDocument.. you add. duplicate. rearrange.. (For more on assigning objects to a layer.

activeLayer = myLayer. see HideOtherLayers. var myNextLayer = myDocument.documents.. (For the complete script..item(myCounter). alert(myString).activeLayer. You can get the active layer using scripting. The script fragment below uses the layer index to iterate through layers. Using relative references Given a layer.name + "\r". . var myLayer = myDocument.layers.name){ myDocument. if(myDocument.name. (For the complete script. } } Note that you can use negative numbers to refer to the layers in the layers collection of a document.item(myCounter). as shown in the following script fragment. as shown in the following script fragment. myCounter++){ //If the layer is not the target layer.) Both methods take a reference layer as a parameter. as shown in the following script fragment.layers. rather than generating an error.layers.documents. myCounter < myDocument. see LayerName.layers. (For the complete script.. for(var myCounter = 0. //Given a document "myDocument".CHAPTER 4: Working with Layers Scripting Layers 52 Getting the active layer The active layer is the layer on which new objects are created. Referring to layers by layer name You also can get a reference to a layer using the name of the layer..item(0). var myString = "The layer below the target layer is " + myNextLayer. see ActiveLayer. Layer -1 refers to the last (bottom) layer in the collection.item(0). or refer to the layer below using the nextItem method.name != myTargetLayer. myString += "The layer above the target layer is " + myPreviousLayer. you can refer to the layer above using the previousItem method. var myDocument = app.activeLayer. hide it. Referring to layers by layer index You can get a reference to a layer using the index of the layer in the layers collection of a document.layers. The previousItem and nextItem methods return an invalid layer reference if the specified (next or previous) layer does not exist.. see RelativeLayerReferences. var myTargetLayer = myDocument.nextItem(myLayer).previousItem(myLayer).layers. (For the complete script.) //Given a document "myDocument".visible = false. var myPreviousLayer = myDocument. var myLayer = myDocument..length.item("Text Layer").layers. myDocument.) //Given a document "myDocument".item(4).) var myLayer = app.

. var myLayerA = myDocument.layers.layers.move(LocationOptions. myDocument. Duplicating layers Use the duplicate method to create a copy of a layer. myLayers.) //Given the layers "myLayer1" and "myLayer2".duplicate(). Moving layers Use the move method to change the stacking order of layers in a document. myLayer.AFTER. (For the complete script.remove().item(4). The following script fragment shows how to get a reference to a range of layers.. as shown in the following script fragment. you can //set a property on all of the layers without iterating. as shown in the following script fragment. (For the complete script.. you can use the itemByRange method.itemByRange(0.item(0). myLayerA. myLayer1..item("Delete This Layer").visible = false.. Deleting layers Use the remove method to delete a layer from a specific document. var myLayer = myDocument.layers. var myLayer = myDocument.index -1). see DeleteLayer. including the page items assigned to them.layers.. then set a property on all layers in the range. see DuplicateLayer. var myLayers = myDocument. //Given a document "myDocument" containing a layer named "Delete This Layer". Merging layers The following script fragment shows how to merge two or more layers. as shown in the following script fragment.. (For the complete script..) //Given a layer "myLayer"..CHAPTER 4: Working with Layers Scripting Layers 53 Referring to ranges of layers To refer to a series of layers. see MergeLayers..) //Given a document "myDocument".) You cannot delete the last remaining layer in a document. myLayerB). see MoveLayer. var myLayerB = myDocument. (For the complete script.activeLayer = myLayer.item(1).layers. (For the complete script.merge(myLayer2)..) //Given a document "myDocument" containing at least two layers. see HideLayersAbove. ar myNewLayer = myLayer. myLayer. //Even though the result contains multiple layers. into a single layer. //Now hide all of the layers above the current layer.

itemLayer = myLayer..add({geometricBounds:[216.layers.add().itemLayer = myDocument.CHARCOAL. just like page items. 144. and other attributes of a layer. var myRectangle = myPage. for(var myCounter = 72.visible = true. (For the complete script. } //Move all of the ovals on the page to a specific layer.item("Ovals"). see AssignPageItemsToLayers. myLayer. (For the complete script.CHAPTER 4: Working with Layers Scripting Layers 54 Assigning page items to layers You can assign a page item to a layer by either referring to the layer when you create the page item (the add method of all page items can take a layer as a parameter) or setting the itemLayer property of an existing page item. 144.name = "myLayer".ovals." and a document "myDocument. //Move all of the guides on the page to the new layer.layers.add(myDocument.layers. the highlight color of the layer.ovals.itemLayer = myDocument. myCounter+10]}). //Create a series of ovals. The following script fragment shows how to work with the guides on a layer. myLayer. myLayer. myLayer. 226. myLayer. //Create a rectangle on the current target layer.ignoreWrap = false. myPage.item("TextFrames")). (For the complete script. the visibility of the layer. Working with layer guides Guides can be assigned to a specific layer.layerColor = UIColors. 144]..item("Rectangles"). myCounter. var myLayer = myDocument.add({geometricBounds:[72. color. //Create a new layer.geometricBounds = [72. myPage. visibility.) //Given a document "myDocument".everyItem(). myLayer. myRectangle..guides." //create a text frame on a layer named "TextFrames" var myTextFrame = myPage.) //Given a document "myDocument" and a page "myPage" containing at least one guide.everyItem(). 144. This section shows how to work with layer properties. and you can lock or unlock the guides on a layer. myTextFrame.layers. and whether text objects on the layer ignore text-wrap settings.lockGuides = true.rectangles. Setting layer properties Layer properties control the layer name. //Move the rectangle to a specific layer. Setting basic layer properties Basic layer properties include the name of the layer. myCounter < 172.textFrames. . see LayerGuides. var myLayer = myDocument.) //Given a reference to a page "myPage.showGuides = true. see BasicLayerProperties.layers. 216]}). 72. myCounter+=10){ myPage.. The following script fragment shows how to set these basic properties of a layer.add(). You can choose to show or hide the guides for a layer. The following script fragment shows how to assign a page item to a layer using both techniques.

printable = false. (For the complete script. myDocument. myLanguageCounter < myDocument..item(myLanguageCounter). myDocument.". case 1: myVersion = "Language B". (For the complete script.item(myLanguageCounter). File(myFileName)).. myTargetLayer.layers.layers.name == "Background")){ myDocument.layers. myFileName.) //Given a document "myDocument". myLanguageCounter. as shown in the following script fragment. break.layers. var myVersion.layers.length-1.exportFile(ExportFormat.item(myLanguageCounter).layers.layers. for(var myCounter = 0.length.locked = true.CHAPTER 4: Working with Layers Scripting Layers 55 Controlling layer printing and visibility You can control the printing and visibility of objects on a layer." //"Language A.pdf".index +1). which means the page items on the layers cannot be edited. "Language B.visible = true.pdfType. } Locking layers Layers can be locked. break. } for(myLanguageCounter = 0. . } else{ myDocument. myCounter < 3.item(myLanguageCounter). see LockLayersBelow.item(myLanguageCounter). case 2: myVersion = "Language C".. myDocument. The following script fragment shows how to lock and unlock layers. var myTargetLayer = myDocument.activeLayer. myCounter ++){ switch(myCounter){ case 0: myVersion = "Language A". var myLayers = myDocument.item(myLanguageCounter). var myFolder = Folder. myLayers." and "Language C.printable = true.) //Given a document "myDocument" containing layers named "Background. see LayerControl..layers. break.layers.name == myVersion)|| (myDocument.desktop. } } myFileName = myFolder + "/" + myVersion + ". myLanguageCounter ++){ if((myDocument.visible = false." export the "Background" //layer and each "Language" layer to PDF as separate PDF files.itemByRange(myDocument.

ellipses. var myRectangle = myPage. 144]}). text frames. create a new rectangle at the default size and location. you are specifying that the page is the container.add(). polygons. Creating Page Items Page items in an InDesign layout are arranged in a hierarchy. create a new rectangle and specify its size and location. When you paste an ellipse into a polygon. 72.. Change the location of a single point. creating a new page item is as simple as telling the object you want to contain the page item to create the page item.rectangles. A rectangle. graphic line. however.add({geometricBounds:[72. in turn. pages. a new rectangle is created on the first page of a new document. buttons. //Given a page "myPage". groups. Open the path and remove two of the four points. closed path containing four path points and having 90 degree interior angles. The rectangle appears at the default location (near the upper left corner of the page) and has a default size (around ten points square). oval. for example. Moving the rectangle and changing its dimensions are both accomplished by filling its geometric bounds property with new values.rectangles. Page item geometry. is always made up of a single. or button). Transforming page items. of the rectangle. //Given a page "myPage".. is a child object of its parent. This hierarchy of containers in the InDesign scripting object model is the same as in the InDesign user interface--when you create a rectangle by dragging the Rectangle tool on a page. Working with paths and path points Creating groups. In general.. Page item types It is important to note that you cannot create a “generic” page item--you have to create a page item of a specific type (a rectangle. or parent. or add another path. and groups) that can appear in an InDesign layout. other page items. This document discusses the following: Creating page items. var myRectangle = myPage. text frame. as shown in the MakeRectangle script. which. and the type of the page item changes to a polygon. In the above script. You will also notice that InDesign changes the type of a page item as the geometry of the page item changes. and InDesign will 56 .5 Working with Page Items This chapter covers scripting techniques related to the page items (rectangles. and appear within a container object of some sort. Spreads. graphic lines. you are specifying that the polygon is the parent of the ellipse. as shown in the MakeRectangleWithProperties script. 144. a page.. and text characters are all examples of objects that can contain page items. Duplicating and moving page items. polygon.

The resulting collection (myAllPageItems) includes all objects on the page. page. Getting the type of a page item When you have a reference to a generic page item. If you use the Control panel in InDesign’s user interface. If no page items on the page have the specified label. var myPageItems = app.pages.item(0).. The resulting collection (myPageItems) does not include objects inside groups (though it does include the group). you probably are already familiar with InDesign’s geometry.item(0).item(0).pageItems. spread.name. Another way to refer to page items is to use their label property.documents. . or polygon are: The number of paths in the object. The number and location of points on the first path in the object. you use the pageItems collection of the container object.item(0). or page items in text frames. alert(myType). and want to find out what type of a page item it is. including items nested inside other page items.documents. use the allPageItems property. var myType = myPageItem. we will get an array of page items whose label has been set to myLabel. The result of the above will be a string containing the type of the page item.name.constructor.item(0).documents. use constructor.item(0). group. To get a reference to all of the items in a given container. graphic line. Referring to page items When you refer to page items inside a given container (a document.pages. Page-item geometry If you are working with page items. This gives you a collection of the top level page items inside the object. To determine the type of a page item. use this example: var myPageItemType = myPageItem.CHAPTER 5: Working with Page Items Creating Page Items 57 change the type to a graphic line. Any page item with more than one path is a polygon.constructor. objects inside other page items (thought it does contain the parent page item). regardless of their position in the hierarchy. layer. The only things that define the type of a rectangle. much as you can use the name property of other objects (such as paragraph styles or layers). //Given a generic page item "myPageItem". For example: var myPageItems = app. it is almost impossible to do anything without understanding the way that rulers and measurements work together to specify the location and shape of an InDesign page item. or page item).name to get the specific type.pageItems("myLabel").pages. but here is a quick summary: Object are constructed relative to the coordinates shown on the rulers. var myAllPageItems = app. ellipse. InDesign returns an empty array. In the following examples.pageItems. text frame..

left direction. [x1. y1]. This array holds the location. [x2. x and y specify the anchor point. The AddPathPoint script shows how to add path points to a path without using the entirePath property. All of the above means that if your scripts need to construct page items. are made up of two or more path points. Paths can be open or closed. or a anchor points and control handles. arrays containing the left direction. [x2. and you may want to set the measurement units in use. and y is the vertical location). in that order): [[xL1. [xR1. Path points contain an anchor point (the location of the point itself ) and two control handles (left direction. The items in the array you use for the entirePath property can contain anchor points only. you can either set the anchor point. in turn.e. and right direction. y1]. Here is an example array containing only anchor point locations: [[x1. [xR1.. .. Each of these properties contains an array in the form (x. you do not need to worry about the paths and path points that define the shape of the object.] Note that the original path does not have to have the same number of points as you specify in the array—InDesign will add or subtract points from the path as it applies the array to the entirePath property. y1]. y2]. //Move the path point to a specific location. .] Where x and y specify the location of the anchor. in current ruler coordinates.add().paths. [[xL2.item(0). YL1]. . you also need to control the location of the zero point. which. as we did in the earlier example in this chapter. [xR2. [x2. //Given a graphic line "myGraphicLine". or you can use the entirePath property of the path to set all of the path point locations at once (as shown in the DrawRegularPolygon_Fast script)... Here is an example containing fully-specified path points (i... [x1. yR2]]..] Where xL and yL specify the left direction.pathPoints. as shown in the following example: [[[xL1. y) (where x is the horizontal location of the point. which controls the curve of the line segment preceding the point on the path. In some cases. and xR and yR specify the right direction. and text frames can be created by specifying their geometric bounds. Rectangles.. however. yR1]].anchor = [144. .. y2]. and right direction of each path point on the path individually (as shown in the DrawRegularPolygon_Slow script). The latter approach is much faster. YL1]. myPathPoint. ellipses. The DeletePathPoint script shows how to delete a path point from a path. which controls the curve of the segment following the point). you may want to construct or change the shape of a path by specifying path point locations. Working with paths and path points For most simple page items. YL2]. anchor. y2]. 144]. and right direction. yR1]]. You can also mix the two approaches. Page items are made up of one or more paths. var myPathPoint = myGraphicLine. of the point or control handle.CHAPTER 5: Working with Page Items Creating Page Items 58 Changing the zero point location by either dragging the zero point or by changing the ruler origin changes the coordinates on the rulers.

move(undefined. myArray. //To move a page item to another document. formatting.remove().. or content of the page items in the group.item(1)). as shown in the Ungroup script. you can move page items by selecting them and dragging them to a new location. [12.push(myPage. There is no need to ungroup a group to change the shape. Both parameters consist of an array of two measurement units. Grouping Page Items In the InDesign user interface.pathPoints. or by choosing Duplicate. simply get a reference to the page item you want to change. //Given a group "myGroup". //Group the items. remove the //last path point in the first path. 12]).ovals. Instead.item(0). optionally.CHAPTER 5: Working with Page Items Grouping Page Items 59 //Given a polygon "myPolygon".item(0)). you tell the object containing the page items you want to group (usually a page or spread) to group the page items. The move method can take one of two optional parameters: moveTo and moveBy. myPage. var myArray = new Array.. //Move the rectangle to another page (rectangle appears at (0.rectangles. myArray. 12]).add(myArray). you create groups of page items by selecting them and then choosing Group from the Object menu (or by pressing the corresponding keyboard shortcut). .item(1)). moveBy specifies how far to move the page item relative to the current location of the page item itself..item(0). //Given a reference to a rectangle "myRectangle". you tell the group itself to ungroup.paths. consisting of a horizontal value and a vertical value.rectangles. //Relative move (note undefined first parameter): myRectangle. In InDesign scripting.pages.ungroup(). myPageItems = myGroup.push(myPage. moveTo specifies an absolute move to the location specified by the array. just as you would with any other page item.add(). by holding down Option/Alt as you drag an object. To ungroup. //Move the rectangle *by* 12 points horizontally. var myPage = app. Paste In Place. You can also create copies of page items by copying and pasting. //Add the items to the array. relative to the current location of the zero point.move(myPage). //Move the rectangle to the location (12. Duplicating and Moving Page Items In the InDesign user interface.item(0)). myArray. 12).documents.0). you can use the move method to change the location of page items. myRectangle. and the duplicate method to create a copy of a page item (and.groups. 12 points vertically.. use the duplicate method. or Step and Repeat from the Edit menu.item(-1).. The Move script shows the difference between these two approaches. //Absolute move: myRectangle. //Given a page "myPage" containing at least two ovals and two rectangles.push(myPage. myArray. In InDesign scripting.push(myPage.. myPolygon.move([12. move it to another location).ovals. as shown in the Group script.

item(0).pages. regardless of the types of the objects used to create the compound path. 12]). it is deleted from the original document.releaseCompoundPath().. refer to the MakeCompoundPath script). but scripts using on these methods require that you select objects (to copy) and rely on the current view to set the location of the pasted elements (when you paste). //Duplicate the rectangle and move the //duplicate to the location (12.duplicate([12. 12 points vertically. myRectangle. This means that scripts that use copy and paste tend to be more fragile (i. 12]). Using Pathfinder operations The InDesign Pathfinder features offer ways to work with relationships between page items on an InDesign page. or create a new page item from the area of intersection of two or more page items. //Given a rectangle "myRectangle" and an Oval "myOval". To release a compound path and convert each path in the compound path into a separate page item. the duplicate method creates a “clone” of an object in the same location as the original object. use the duplicate method (see below). more likely to fail) than scripts that use duplicate and move. var myDuplicate = myRectangle.makeCompoundPath(myOval). To move the object to another while retaining the original. var myDocument = app. or subtract the area of one page item from another page item.. //Given a reference to a rectangle "myRectangle".. When you create a compound path. refer to the ReleaseCompoundPath script). use the releaseCompoundPath method of a page item. //Duplicate the rectangle to another document.add(). You can also use copy and paste in InDesign scripting.item(0)).CHAPTER 5: Working with Page Items Duplicating and Moving Page Items 60 Note that the move method truly moves the object—when you move a page item to another document. var myPageItems = myPolygon...pages. var myDuplicate = myRectangle.documents.0). //Absolute move: var myDuplicate = myRectangle. //Given a polygon "myPolygon". //Relative move (note undefined first parameter): var myDuplicate = myRectangle.duplicate(myDocument. //Duplicate the rectangle to another page (rectangle appears at (0.. By default. Use the duplicate method to create a copy of a page item. [12. Optional parameters can be used with the duplicate method to move the duplicated object to a new location (including other pages in the same document. var myPage = app. try to write scripts that do not depend on the current view or selection state. as shown in the following script fragment (for the complete script. 12). //Duplicate the rectangle and move the duplicate *by* 12 //points horizontally.duplicate(undefined.duplicate(myPage).e. Creating compound paths InDesign can combine the paths of two or more page items into a single page item containing multiple paths using the Object > Paths > Make Compound Path menu option. Every page . You can merge the paths of page items. You can do this in InDesign scripting using the makeCompoundPath method of a page item. or to another document entirely). as shown in the following script fragment (for the complete script. the type of the resulting object is polygon.add(). Whenever possible.documents..

refer to AddPath).. as shown in the following script fragment (for the complete script.. as shown in the following script fragment (for the complete script. refer to OpenPath). myRectangle. for example. //Given a rectangle "myRectangle". myRectangle..addPath(myOval). refer to ExcludeOverlapPath).. //Given a rectangle "myRectangle" and an Oval "myOval". myRectangle. as shown in the following script fragment (for the complete script.convertShape(ConvertShapeOptions. Note that it is very likely that the type of the object will change after you apply one of the Pathfinder operations. ExcludeOverlapPath. IntersectPath.. as shown in the following script fragment (for the complete script. In InDesign scripting.subtractPath(myRetangle).convertToRoundedRectangle). refer to MinusBack)..minusBack(myOval). The excludeOverlapPath method creates a new path based on the non-intersecting areas of two or more overlapping page items. Converting page-item shapes InDesign page items can be converted to other shapes using the options in the Object > Convert Shape menu or the Pathfinder panel (Window > Object and Layout > Pathfinder). as shown in the following script fragment (for the complete script.. //Given a rectangle "myRectangle" and an Oval "myOval". The minusBack method removes the area of intersection of the back-most object from the page item or page items in front of it. myRectangle. you would use something like the approach shown in the following fragment (for the complete script. .. page items support the convertShape method. MinusBack. //Given a rectangle "myRectangle" and an Oval "myOval". myRectangle. The intersectPath method creates a new page item from the area of intersection of two or more page items. Which object type it will change to depends on the number and location of the points in the path or paths resulting from the operation..excludeOverlapPath(myOval). The subtractPath method removes the area of intersection of the frontmost object from the page item or page items behind it. //Given a rectangle "myRectangle" and an Oval "myOval". To merge two page items into a single page item. All of the Pathfinder methods work the same way--you provide an array of page items to use as the basis for the operation (just as you select a series of page items before choosing the Pathfinder operation in the user interface). refer to IntersectPath).. refer to SubtractPath). myOval.. as demonstrated in the following script fragment (for the complete script. //Given a rectangle "myRectangle" and an Oval "myOval". refer to ConvertShape).intersect(myOval)..CHAPTER 5: Working with Page Items Duplicating and Moving Page Items 61 item supports the following methods related to the Pathfinder features: AddPath. The convertShape method also provides a way to open or close reverse paths. and SubtractPath.

2. .. as shown in the following script fragment (for the complete script. shear. myLayer. This one method replaces the resize. refer to MoveLayer). Arranging page items Page items in an InDesign layout can be arranged in front of or behind each other by adjusting their stacking order within a layer. you can specify its layer. or transformation origin.. rotate. myRectangle. refer to ItemLayer). //send the rectangle to the layer. rotate. myRectangle.. but you can also move a page item from one layer to another.bringToFront(). Using the transform method The transform method requires a transformation matrix (transformationMatrix) object that defines the transformation or series of transformations to apply to the object. When you do this.layers. myRectangle. Create a transformation matrix. app. or can be placed on different layers. and how to control the stacking order of objects relative to each other (for the complete script. For more on coordinate systems. Apply the transformation matrix to the object using the transform method. you specify the center of transformation. or translate operations.. The stacking order of layers in a document can also be changed using the move move method of the layer itself.item("myLayer"). shearing (skewing). see “Transformation origin” on page 66. you apply transformations using the transform method.. as shown in the following script fragment (for the complete script. A transformation matrix can contain any combination of scale. //Given a rectangle "myRectangle" and a layer "myLayer". The order in which transformations are applied to an object is important. bring //the rectangle to the front.item(0). For more on specifying the transformation origin.Documents.itemLayer = app. In addition. and movement (or translation). To transform an object.item(-1)..item(-1)). //where "myOval" is in front of "myRectangle". rotation. Transforming Page Items Transformations include scaling. refer to StackingOrder). and shear methods used in versions of InDesign prior to InDesign CS3 (5.layers. see “Coordinate spaces” on page 65. The following script fragment shows how to bring objects to the front or back of their layer.convertToOpenPath). When you create a page item. The item layeritemLayerItemLayer property of the page item is the key to doing this. //Given a layer "myLayer".convertShape(ConvertShapeOptions. In scripting. Applying transformations in differing orders can produce very different results.move(LocationOptionsafter.0).CHAPTER 5: Working with Page Items Transforming Page Items 62 //Given a rectangle "myRectangle". you also specify the coordinate system in which the transformation is to take place.documents. you follow two steps: 1. move the layer behind //the default layer (the lowest layer in the document //is layers. //Given a rectangle "myRectangle" and an oval "myOval".item(0).

topLeftAnchor]. myTransformationMatrix = myTransformationMatrix.pasteboardCoordinates. refer to the Transform script. verticalScaleFactor:. AnchorPoint.centerAnchor. undefined.rotateMatrix(45).transformationMatrices. myRectangle. var myShearMatrix =app. myRectangle. undefined. undefined.rotateMatrix(15). myShearMatrix).rotateMatrix(undefined.25881904510252 is the sine of 15 degrees. AnchorPoint. AnchorPoint. myTransformationMatrix = myTransformationMatrix.transform(CoordinateSpaces. myTransformationMatrix = myTransformationMatrix. 0. For a script that “wraps” transformation routines in a series of easy-to-use functions. but a variety of methods can interact with the transformation matrix to create a new transformation matrix based on the existing transformation matrix. In the following examples. var myScaleMatrix = app. true). //Shear a transformation matrix by 15 degrees.96592582628907. .pasteboardCoordinates.transformationMatrices. 72]).transform(CoordinateSpaces.pasteboardCoordinates. as shown in the ShearMatrix script.pasteboardCoordinates. myRectangle. //The following statements are equivalent //(0.transformationMatrices.96592582628907). myRotateMatrix).5.5).add({counterclockwiseRotationAngle:27}).pasteboardCoordinates. (For the complete script. When you use the shearMatrixmethod. var myRotateMatrix = app. var myScaleMatrix = app. AnchorPoint.add({horizontalScaleFactor:. (For the complete script. myRotateMatrix.5}). Working with transformation matrices A transformation matrix cannot be changed once it has been created. true). see TransformMatrix. var myRotateMatrix = app.transform(CoordinateSpaces. . 72]). //Rotate a transformation matrix by 45 degrees. AnchorPoint. the cosine). 72].shearMatrix(15).add({clockwiseShearAngle:30}).25881904510252). myScaleMatrix. myRectangle.5.add({horizontalScaleFactor:. as shown in the RotateMatrix script. verticalScaleFactor:. //Rotate a rectangle "myRectangle" around a specified ruler point ([72.add({counterclockwiseRotationAngle:27}).5. you can provide a slope. 0.transform(CoordinateSpaces. we show how to apply transformations to a transformation matrix and replace the original matrix. rather than an angle in degrees. you can use a sine or cosine value to transform the matrix. var myTransformationMatrix = myTransformationMatrix. //Shear a rectangle "myRectangle" around its center point. myTransformationMatrix = myTransformationMatrix. 0. myTransformationMatrix = myTransformationMatrix.5}). //Scale a rectangle "myRectangle" around its center point. [[72. myRectangle.topLeftAnchor]. see TransformExamples.transformationMatrices.centerAnchor. myScaleMatrix). //Scale a rectangle "myRectangle" around a specified ruler point ([72.transformationMatrices.centerAnchor. 72]. [[72.) //Scale a transformation matrix by 50% in both horizontal and vertical dimensions. rather than an angle in degrees.rotateMatrix(undefined.) //Rotate a rectangle "myRectangle" around its center point.transform(CoordinateSpaces. When you use the rotateMatrix method.CHAPTER 5: Working with Page Items Transforming Page Items 63 The following scripting example demonstrates the basic process of transforming a page item.scaleMatrix(.

var myTransformationMatrixB = app. You can add transformation matrices using the catenateMatrixmethod. see CatenateMatrix. as shown in the following example. myTransformationMatrix). myNewRectangle. myRectangle.shearMatrix(undefined.transformationMatrices. as shown in the following example. //Rotate the duplicated rectangle.add({counterclockwiseRotationAngle:30. myTransformationMatrix).centerAnchor.item(0). (For the complete script. using the transformValuesOf method. //The duplicated rectangle will be both moved and rotated.) var myTransformationMatrixA = app.centerAnchor.invertMatrix().catenateMatrix(myTransformationMatrixB). myNewRectangle. slope = rise/run--so //the slope of 45 degrees is 1.pasteboardCoordinates. myTransformationMatrixA).) You can use the inverted transformation matrix to undo the effect of the matrix. var myNewRectangle = myRectangle. You can get the inverse of a transformation matrix using the invertMatrixmethod.transformationMatrices.duplicate(). see InvertMatrix. see TransformValuesOf. var myNewRectangle = myRectangle. AnchorPoint. AnchorPoint.transform(CoordinateSpaces.item(0). myTransformationMatrix = myTransformationMatrix. you can get the transformation matrix that was applied to it.pasteboardCoordinates.shearMatrix(45). var myTransformationMatrix = app. verticalTranslation:12}).add({counterclockwiseRotationAngle:30}).transform(CoordinateSpaces. AnchorPoint.centerAnchor.pasteboardCoordinates. When an object is transformed.transform(CoordinateSpaces. AnchorPoint.item(0). myRectangle. AnchorPoint. var myRectangle = app. myTransformationMatrix = myTransformationMatrixA.duplicate(). //Move the duplicated rectangle to the location of the original //rectangle by inverting.transform(CoordinateSpaces.CHAPTER 5: Working with Page Items Transforming Page Items 64 //The following statements are equivalent. (For the complete script. (For the complete script. myTransformationMatrix = myTransformationMatrix. myTransformationMatrix).rectangles.pages.add({horizontalTranslation:12.item(0). myTransformationMatrix = myTransformationMatrix.item(0). myNewRectangle = myRectangle.pasteboardCoordinates. //Merge the two transformation matrices. var myRectangle = app.duplicate(). as shown in the following script fragment. horizontalTranslation:12.) . //Move the duplicate (unrotated) rectangle.centerAnchor.documents. myNewRectangle = myRectangle. 1). verticalTranslation:12}).documents. myNewRectangle.pasteboardCoordinates.pages. then applying the transformation matrix.duplicate().item(-1).transformationMatrices.rectangles. myTransformationMatrixB).transform(CoordinateSpaces.centerAnchor.

and does not correspond to the rulers you see in the user interface. Any transformations applied to the parent affect the parent coordinates. Transformations applied to objects have no effect on this coordinate space (e.parentCoordinates). (For the complete script. NOTE: The values in the horizontal. the angle of the horizontal and vertical axes do not change). nor does it have anything to do with the pasteboard area you can see around pages in the InDesign user interface. CoordinateSpaces. alert(myString). in pasteboard coordinates. rotating the parent object changes the angle of the horizontal and vertical axes of this coordinate space.verticalTranslation.horizontalTranslation. myString += "Vertical Scale Factor: " + myYScale + "\r". in which the transform operation occurs.pasteboardCoordinates enumeration provided as a parameter for the transform method.counterclockwiseRotationAngle.transformValuesOf(CoordinateSpaces. The origin of this space is at the center of the spread. myString += "Shear Angle: " + myShearAngle + "\r". var myShearAngle = myTransformationMatrix. see CoordinateSpaces.) . var myString = "Rotation Angle: " + myRotationAngle + "\r". the parent object refers to the group or page item containing the object.CHAPTER 5: Working with Page Items Transforming Page Items 65 //Note that transformValuesOf() always returns an array //containing a single transformationMatrix.and vertical-translation fields of the transformation matrix returned by this method are the location of the upper-left anchor of the object. myString += "Horizontal Scale Factor: " + myXScale + "\r". myString += "Vertical Translation: " + myYTranslate + "\r". var myTransformationMatrix = myTransformArray[0].horizontalScaleFactor.pasteboardCoordinates is the coordinate space of the entire InDesign document.. if the parent of the object is a page or spread. parent coordinates are the same as spread coordinates. myString += "Horizontal Translation: " + myXTranslate + "\r".innerCoordinates is the coordinate space in which the object itself was created. The coordinate space can be one of the following values: CoordinateSpaces. It does not correspond to InDesign’s rulers or zero point.spreadCoordinates is the coordinate space of the spread. CoordinateSpaces. var myXTranslate = myTransformationMatrix. This parameter determines the system of coordinates. This coordinate space extends behind all spreads in a document. var myTransformArray = myRectangle.clockwiseShearAngle.verticalScaleFactor. or coordinate space. The following script shows the differences between the coordinate spaces.parentCoordinates is the coordinate space of the parent of the object. In this case. var myXScale = myTransformationMatrix. var myYTranslate = myTransformationMatrix. you might have noticed the CoordinateSpaces. var myRotationAngle = myTransformationMatrix. var myYScale = myTransformationMatrix. CoordinateSpaces. for example. Coordinate spaces In the transformation scripts we presented earlier.g.

transformationMatrices. [AnchorPoint. BoundingBoxLimits.geometricPathBounds) or the visible bounds of the object (BoundingBoxLimits.item(0). the top-left corner of the bounding box is (0.outerStrokeBounds.select(myRectangle). [[.item(0). alert("Transformed by parent coordinates.item(-1). the bottom-right corner. myTransformationMatrix).undo().rectangles. AnchorPoint. app. //Transform using pasteboard coordinates.transform(CoordinateSpaces.outerStrokeBounds] .").add({horizontalScaleFactor:2}). var myTransformationMatrix = app.y). app. [AnchorPoint. BoundingBoxLimits.geometricPathBounds) or the visible bounds of the object (BoundingBoxLimits. myRectangle.pasteboardCoordinates] (x.item(0). BoundingBoxLimits. app.select(myRectangle). bounds type — A point specified relative to the geometric bounds of the object (BoundingBoxLimits.parentCoordinates.CHAPTER 5: Working with Page Items Transforming Page Items 66 var myRectangle = app.outerStrokeBounds).bottomLeftAnchor. CoordinateSpaces.groups.centerAnchor. In this case.5].centerAnchor anchor. The transformation origin can be specified in several ways: Bounds space: anchor — An anchor point on the object itself.item(0).centerAnchor.item(0).undo(). app.transform(CoordinateSpaces. Transformation origin The transformation origin is the center point of the transformation. .transform(CoordinateSpaces. //Transform using parent coordinates. . AnchorPoint.documents. //Undo the transformation.\rThe rectangle inside the group was\rrotated 45 degrees counterclockwise\rbefore it was added to the group.pasteboardCoordinates.\r\rWatch as we apply a series of scaling\roperations in different coordinate spaces.undo().outerStrokeBounds) in a given coordinate space.bottomLeftAnchor. myRectangle.select(myRectangle).").geometricPathBounds) or the visible bounds of the object (BoundingBoxLimits."). AnchorPoint. myTransformationMatrix).outerStrokeBounds] anchor.5.5).innerCoordinates.pages.documents."). coordinate system — An anchor point specified as the geometric bounds of the object (BoundingBoxLimits.documents. alert("Transformed by inner coordinates. alert("The page contains a group which has been\rrotated 45 degrees (counterclockwise). bounds type — An anchor point specified relative to the geometric bounds of the object (BoundingBoxLimits. 0). bounds type. //Select the rectangle and display an alert. app. The center anchor is located at (. alert("Transformed by pasteboard coordinates. AnchorPoint. app.outerStrokeBounds).item(0). 1). //Transform the rectangle using inner coordinates. (1. myTransformationMatrix).5. myRectangle.documents.centerAnchor.

) var myPageLocation = myRectangle. AnchorPoint. 144]. It can be specified relative to the object’s geometric or visible bounds. undefined.outerStrokeBounds) in a given coordinate space. the top-left corner of the bounding box is (0.CHAPTER 5: Working with Page Items Transforming Page Items 67 (x. you need to get the location of a point specified in one coordinate space in the context of another coordinate space. coordinate system — A point in the specified coordinate space. //resolve() returns an array containing a single item. -100] based //on that page. as shown in the following script example. 1). you use the resolve method. //Rotate the rectangle around the ruler location [-100. alert("X: " + myPageLocation[0][0] + "\rY: " + myPageLocation[0][1]). . Setting the considerRulerUnits parameter to true makes //certain that the transformation uses the current ruler units. CoordinateSpaces. [[.5].transform(CoordinateSpaces.5). the bottom-right corner. 72] (x. y). CoordinateSpaces. true). y) — A point in the pasteboard coordinate space. BoundingBoxLimits. page index — A point. and it can be specified in a given coordinate space. y).pasteboardCoordinates.pasteboardCoordinates] Ruler space: (x. (For the complete script. see ResolveLocation.geometricPathBounds) or the visible bounds of the object (BoundingBoxLimits. AnchorPoint. In this case. true). //The transformation gets the ruler coordinate [-100. coordinate space — A point specified relative to the geometric bounds of the object (BoundingBoxLimits. . //Note that the anchor point specified here specifes the page //containing the point--*not* that transformation point itself. -100].transform(CoordinateSpaces. myTransformationMatrix. CoordinateSpaces. myNewRectangle. bounds type. y). [[72. -100]. 72]. The center anchor is located at (. y)) — A point in the coordinate space given as the in parameter of the transform method. 72]] The following script example shows how to use some of the transformation origin options. AnchorPoint. [72. AnchorPoint.outerStrokeBounds.5. 72]. Location can be specified as an anchor point or a coordinate pair.) //Rotate around the duplicated rectangle's center point.parentCoordinates] ((x. [[72. see TransformationOrigin. 0] (x. [[72. 0).pasteboardCoordinates.pasteboardCoordinates. Resolving locations Sometimes. To do this.5. myNewRectangle. 144]. [[-100.topLeftAnchor]. relative to the parent page of the specified location of the object. .centerAnchor] Transform space: (x. y). (For the complete script.resolve([[72.centerAnchor. (1.topRightAnchor]. [[72. location — A point. relative to the ruler origin on a specified page of a spread. myTransformationMatrix).

if((myCenterPoint[0] != 0)||((myCenterPoint[1] != 0))){ var myTranslateMatrix = app. myPolygon. } myTransformedPoint = myRotateMatrix.entirePath = myPathPoints.add(). myPointCounter < myNumberOfPoints.changeCoordinates(myPoint).transformationMatrices. false if it is not.item(0). myPolygon. var myPoint = [0.pasteboardCoordinates. as shown in the FunWithTransformations sample script. function myDrawPolygon(myParent.changeCoordinates(myPoint).add({ horizontalTranslation:myCenterPoint[0].add({ horizontalTranslation:myInnerRadius}).paths. myCenterPoint. myStarInset){ var myTransformedPoint. //If the center point is somewhere other than [0.add({ counterclockwiseRotationAngle:myAngle}). myPointCounter ++){ //Translate the point to the inner/outer radius.changeCoordinates(myTransformedPoint).centerAnchor. myStarPolygon. } } //This function returns true if myNumber is even.add({ horizontalTranslation:myRadius}). myPathPoints.transformationMatrices.0]. if ((myStarInset == 1)||(myIsEven(myPointCounter)==true)){ myTransformedPoint = myOuterTranslateMatrix. } //Create a new polygon. } var myInnerRadius = myRadius * myStarInset. return myResult. myTranslateMatrix).transformationMatrices. //Set the entire path of the polygon to the array we've created.CHAPTER 5: Working with Page Items Transforming Page Items 68 Transforming points You can transform points as well as objects. AnchorPoint. which means scripts can perform a variety of mathematical operations without having to include the calculations in the script itself. var myAngle = 360/myNumberOfPoints. verticalTranslation:myCenterPoint[1]}). . if(myStarPolygon == true){ myNumberOfPoints = myNumberOfPoints * 2. } else{ myTransformedPoint = myInnerTranslateMatrix.rotateMatrix(myAngle). } You also can use the changeCoordinates method to change the positions of curve control points.transformationMatrices. function myIsEven(myNumber){ var myResult = (myNumber%2)?false:true.0].polygons. var myPathPoints = new Array. myNumberOfPoints. var myPolygon = myParent. myRotateMatrix = myRotateMatrix. var myRotateMatrix = app. var myOuterTranslateMatrix = app.transform(CoordinateSpaces.push(myTransformedPoint). var myInnerTranslateMatrix = app. for (var myPointCounter = 0. myRadius. //translate the polygon to the center point. The ChangeCoordinates sample script shows how to draw a series of regular polygons using this approach: //General purpose routine for drawing regular polygons from their center point.

add({counterclockwiseRotationAngle:45}).pasteboardCoordinates. undefined.item(0). true).transformAgain(). (For the complete script.transformAgain(). These methods change the location of the path points of the page item without scaling the content or stroke weight of the page item. myTransformationMatrix). myRectangleB.duplicate().transformationMatrices.transformAgain(). myRectangleE.transformAgain(). Resize and Reframe In addition to scaling page items using the transform method.rectangles. [[0.transformAgain(). myRectangleD. var myRectangleD = myRectangleC. myRectangleC.duplicate(). see Resize. myTransformationMatrix). //Given a reference to a rectangle "myRectangle".pasteboardCoordinates.. myRectangleG. myY1+12.duplicate(). myRectangleD. For the complete script. 2]). var myBounds = myRectangle. myRectangleH.duplicate().resize(CoordinateSpaces.duplicate(). myDuplicate.centerAnchor.topLeftAnchor]. var myRectangleE = myRectangleD. var myRectangleF = myRectangleE.transform(CoordinateSpaces. myX1-12.) var myRectangle = myPage. There are four methods for applying transformations again: transformAgain transformAgainIndividually transformSequenceAgain transformSequenceAgainIndividually The following script fragment shows how to use transformAgain. myRectangleH. var myY1 = myBounds[0]. var myRectangleA = myPage.transformAgain().pasteboardCoordinates. you can also change the size of the shape using two other methods: resize and reframe.duplicate(). var myRectangleB = myRectangleA.duplicate().add({geometricBounds:[myY1-12. var myDuplicate = myRectangle. ResizeMethods.. AnchorPoint.transformAgain().transform(CoordinateSpaces.geometricBounds. myRectangleF. see TransformAgain. var myTransformationMatrix = app. . myTransformationMatrix.rectangles.transformAgain().centerAnchor. myX1+12]}).transform(CoordinateSpaces.transformAgain(). The following script fragment shows how to use the resize method. AnchorPoint.innerCoordinates. var myRectangleG = myRectangleF. you can do so using scripting.multiplyingCurrentDimensionsBy. var myRectangleH = myRectangleG. var myRectangleC = myRectangleB. [2. myRectangleB. myRectangleF. AnchorPoint. var myX1 = myBounds[1].duplicate(). AnchorPoint.CHAPTER 5: Working with Page Items Resize and Reframe 69 Transforming again Just as you can apply a transformation or sequence of transformations again in the user interface.0].centerAnchor. myRectangleA.

myDuplicate = myRectangle.. //Given a reference to a rectangle "myRectangle". var myY2 = myBounds[2]+72. myX2]]). [[myY1.CHAPTER 5: Working with Page Items Resize and Reframe 70 The following script fragment shows how to use the reframe method. .. var myY1 = myBounds[0]-72. myDuplicate.[myY2. var myX2 = myBounds[3]+72. var myX1 = myBounds[1]-72. var myBounds = myRectangle.duplicate().geometricBounds. For the complete script. see Reframe.innerCoordinates.reframe(CoordinateSpaces. myX1].

documents. //Create a text frame on the current page.documents. myTextFrame. or place text files on pages using scripting.geometricBounds = myGetBounds(myDocument. var myTextFrame = myPage.pages. and formatting text are the tasks that make up the bulk of the time spent working on most InDesign documents. Creating a text frame The following script creates a text frame. //Set the bounds of the text frame. contents:"This is some example text. 288." //Note that you could also use a properties record to //create the frame and set its bounds and contents in one line: //var myTextFrame = myDocument.item(0). This chapter shows how to script the most common operations involving text and type." The following script fragment shows the myGetBounds function.item(0).add( {geometricBounds:[72.pages. Entering and Importing Text This section covers the process of getting text into your InDesign documents."}). see MakeTextFrameWithinMargins. We also assume that you have some knowledge of working with text in InDesign and understand basic typesetting terms. var myPage = myDocument. myTextFrame. sets the bounds (size) of the frame. //Enter text in the text frame. 72. We assume that you have already read Adobe InDesign CS5 Scripting Tutorial and know how to create.textFrames. Just as you can type text into text frames and place text files using the InDesign user interface.textFrames.textFrames.item(0). var myTextFrame = myPage. then enters text in the frame (for the complete script. 288]. The following script shows how to create a text frame that is the size of the area defined by the page margins. install. (For the complete script. myGetBounds is a useful function that you can add to your own scripts. myPage). and it appears in many other examples in this chapter. 288]. you can create text frames. //Set the bounds of the text frame. and run a script.) var myDocument = app. see the MakeTextFrame tutorial script): var myDocument = app. 72.item(0). starting with very simple scripts and building toward more complex operations.contents = "This is some example text. myTextFrame.contents = "This is some example text. editing.add().add(). //Enter text in the text frame. 71 .item(0). insert text into a story. var myPage = myDocument. Because of this. myTextFrame. The sample scripts in this chapter are presented in order of complexity.pages. automating text and type operations can result in large productivity gains.geometricBounds = [72.6 Text and Type Entering. 288.

var myX1 = myPage. //("\r" is a return character. var myX2 = myPage. see AddText): //Add text at the end of the text in the text frame. The alerts shows that the text frame does not contain the overset text.documentPreferences.pageHeight if(myPage.myPage. myPage){ var myPageWidth = myDocument. we added text at the end of the parent story rather than at the end of the text frame. } var myY1 = myPage. return [myY1.pageWidth.marginPreferences. You always can get a reference to the story using the parentTextFrame property of a text frame. var myPageHeight = myDocument.marginPreferences. we can guarantee that the text is added.top.parentStory.item(-1). //To do this.CHAPTER 6: Text and Type Entering and Importing Text 72 function myGetBounds(myDocument. Stories and text frames All text in an InDesign layout is part of a story. the following script demonstrates the difference.contents = myNewText. see StoryAndTextFrame).documentPreferences. It can be useful to work with the text of a story instead of the text of a text frame.insertionPoints. regardless of the composition of the text in the text frame. By adding the text to the end of the parent story.side == PageSideOptions.right.marginPreferences. In the preceding script. var myY2 = myPageHeight . and stories can contain multiple text frames.". var myX2 = myPageWidth .bottom. myY2. } Adding text To add text to a story. The following sample script uses this technique to add text at the end of a story (for the complete script.left. but the story does (for the complete script.myX2. Creating a text frame creates a story. use the contents property of the insertion point at the location where you want to insert the text.) var myNewText = "\rThis is a new paragraph of example text. myX2]. that depends on the length and formatting of the text. .marginPreferences.leftHand){ var myX2 = myPage. and every story can contain one or more text frames. myTextFrame.left.marginPreferences. myX1.right. } else{ var myX1 = myPage. This is because the end of the text frame might not be the end of the story.marginPreferences. we'll use the last insertion point in the story.

contents = "a little bit of".parentStory.activePage.activePage.points. alert("The last paragraph in this alert should be \"This is some overset text\".item(-2).insertionPoints. //Fill the text frame with placeholder text. we excluded the return character because deleting the return might change the paragraph style applied to the paragraph.contents).words.contents = "\rThis is some overset text".characters. 288].characters. Alternately.item(1).paragraphs. myDocument.contents). //Now add text beyond the end of the text frame.points.parentStory. //Create a text frame on the current page. myDocument. var myStartCharacter = myTextFrame.paragraphs.activeWindow.contents = TextFrameContents. myDocument. To do this. myEndCharacter). myTextFrame. 72. For more on understanding the relationships between text objects in an InDesign document. var myEndCharacter = myTextFrame. you can use the JavaScript method of explicitly entering Unicode characters by their glyph ID number: \unnnn (where nnnn is the Unicode code for the character). 96. myTextFrame.points. (We omitted the myGetBounds .parentStory. you can simply enter Unicode characters in text strings that you send to InDesign. and we supplied two characters—the starting and ending characters of the paragraph—as parameters.item(2). myTextFrame.contents = "This text replaces the text in paragraph 2.activeDocument.textFrames.viewPreferences. contents:"This is some example text.verticalMeasurementUnits = MeasurementUnits.verticalMeasurementUnits = MeasurementUnits. Replacing text The following script replaces a word with a phrase by changing the contents of the appropriate object (for the complete script. //we'll use the ItemByRange method.item(0).CHAPTER 6: Text and Type Entering and Importing Text 73 var myDocument = app.horizontalMeasurementUnits = MeasurementUnits.geometricBounds = [72. myTextFrame. myDocument. see ReplaceText): //Replace the text in the second paragraph without replacing //the return character at the end of the paragraph. //Set the measurement units to points.add({geometricBounds:[72. alert("The last paragraph in this alert should be \"This is some overset text\". //Set the bounds of the text frame.textFrames.add()."}).item(-1). see “Understanding Text Objects” on page 81.activeDocument.viewPreferences. //Create a text frame on the current page. //Replace the third word "some" with the phrase //"a little bit of". var myTextFrame = app. The following script replaces the text in a paragraph (for the complete script. myTextFrame.itemByRange(myStartCharacter. 72. //Set the measurement units to points. see ReplaceWord): var myDocument = app.activeWindow. Inserting special characters Because the ExtendScript Toolkit supports Unicode. To do this. Is it?\r" + myTextFrame.horizontalMeasurementUnits = MeasurementUnits.viewPreferences.item(1).parentStory. we used ItemByRange method. Is it?\r" + myTextFrame." In the preceding script above.placeholderText.points. 288]. 288.viewPreferences. The following script shows several ways to enter special characters.texts. var myTextFrame = app.

txt"). //Set the bounds of the text frame.contents = "Not equal to: \u2260\rSquare root: \u221A\rParagraph: \u00B6\r".contents = "\r".top.item(0).insertionPoints.pages.parentStory.documents.insertionPoints. Placing Text and Setting Text-Import Preferences In addition to entering text strings. visit http://www.item(0)).add(). //Get the current page.org.contents = "En dash:".viewPreferences.insertionPoints.place(File("/c/test.autoPageNumber.marginPreferences. //Set the measurement units to points.viewPreferences.item(0).item(0).place(): //File as File object.points. To learn more about Unicode.points. undefined. var myStory = myPage. you can find it in “Creating a text frame” on page 71” or in the SpecialCharacters tutorial script.item(-1).parentStory.enDash.item(-1). The easiest way to find the Unicode ID for a character is to use InDesign’s Glyphs palette: move the cursor over a character in the palette. //Get the top and left margins to use as a place point. var myX = myPage.insertionPoints.horizontalMeasurementUnits = MeasurementUnits.geometricBounds = myGetBounds(myDocument.verticalMeasurementUnits = MeasurementUnits.insertionPoints.item(-1). you can place text files created using word processors and text editors.contents = SpecialCharacters. //Create a text frame on the current page. false.parentStory.insertionPoints.marginPreferences. myTextFrame. myTextFrame.textFrames. myTextFrame. myDocument. y]] //[DestinationLayer as Layer object] //[ShowingOptions as Boolean = False] //[Autoflowing as Boolean = False] //You'll have to fill in your own file path. //Entering InDesign special characters by their enumerations: myTextFrame.parentStory.contents = SpecialCharacters. myTextFrame.contents = "\r". var myPage = myDocument.insertionPoints.parentStory. //[PlacePoint as Array [x.pages.item(-1).parentStory. //Entering special characters directly.item(-1). //Note that if the PlacePoint parameter is inside a column. myDocument.insertionPoints. [myX.parentStory.) var myDocument = app. myTextFrame.contents = SpecialCharacters. myY].parentStory. . myDocument.item(-1). see PlaceTextFile): var myDocument = app.item(-1). //Parameters for Page.sectionSymbol. //Entering special characters by their Unicode glyph ID value: myTextFrame. var myY = myPage. only the vertical (y) //coordinate will be honored--the text frame will expand horizontally to fit the column.item(-1). true)[0].contents = "Automatic page number marker:".contents = "\r". myTextFrame.parentStory.item(-1).CHAPTER 6: Text and Type Placing Text and Setting Text-Import Preferences 74 function from this listing.parentStory. myTextFrame.insertionPoints. myTextFrame. The following script shows how to place a text file on a document page (for the complete script. //Autoflow a text file on the current page. var myTextFrame = myDocument.item(-1).contents = "Registered trademark: Æ\rCopyright: ©\rTrademark: ?\r". and InDesign displays its Unicode value.pages.unicode.documents. myTextFrame.left.insertionPoints.contents = "Section symbol:".item(0). myTextFrame.

myTextFrame.add({geometricBounds:myGetBounds(myDocument. you can find it in “Creating a text frame” on page 71. //[ShowingOptions as Boolean = False] //You'll have to fill in your own file path.tagFileDefinition styleConflict = StyleConflict. myTextFrame.place(File("/c/test.CHAPTER 6: Text and Type Placing Text and Setting Text-Import Preferences 75 The following script shows how to place a text file in an existing text frame.UTF8. //Place a text file at the end of the text.publicationDefinition. //styleConflict property can be: //StyleConflict. such as French.item(-1). useTypographersQuotes = true. var myTextFrame = myPage.taggedTextImportPreferences){ removeTextFormatting = false. with(app. } The following script shows how to set tagged text import preferences (for the complete script. var myPage = myDocument.item(0).item(0).place(File("/c/test. spacesIntoTabsCount = 3.) var myDocument = app. dictionary = "English: USA". var myTextFrame = myPage. convertSpacesIntoTabs = true. //[ShowingOptions as Boolean = False] //You'll have to fill in your own file path. The comments in the script show the possible values for each property.item(0). The following script shows how to set text-import preferences (for the complete script. //Parameters for InsertionPoint.documents. //The dictionary property can take many values. //Parameters for TextFrame.macintosh.myPage)}).parentStory.place(): //File as File object. stripReturnsBetweenLines = true. The following script shows how to insert a text file at a specific location in text. use the corresponding import-preferences object.txt")).textImportPreferences){ //Options for characterSet: TextImportCharacterSet. you can find it in “Creating a text frame” on page 71. var myPage = myDocument.pages. see TaggedTextImportPreferences): with(app. To specify the import options for the specific type of text file you are placing.item(0). see TextImportPreferences). //Place a text file in the text frame.textFrames. characterSet = TextImportCharacterSet. (We omitted the myGetBounds function from this listing.insertionPoints.pages. stripReturnsBetweenParagraphs = true. //platform options: ImportPlatform platform = ImportPlatform.item(0).txt")).publicationDefinition //StyleConflict. useTypographersQuotes = true.) var myDocument = app.place(): //File as File object.documents. (We omitted the myGetBounds function from this listing. Italian. } .” or see the PlaceTextFileInFrame tutorial script.textFrames.” or see the InsertTextFile tutorial script.

CHAPTER 6: Text and Type

Placing Text and Setting Text-Import Preferences

76

The following script shows how to set Word and RTF import preferences (for the complete script, see WordRTFImportPreferences):
with(app.wordRTFImportPreferences){ //convertPageBreaks property can be: //ConvertPageBreaks.columnBreak //ConvertPageBreaks.none //ConvertPageBreaks.pageBreak convertPageBreaks = ConvertPageBreaks.none; //convertTablesTo property can be: //ConvertTablesOptions.unformattedTabbedText //ConvertTablesOptions.unformattedTable convertTablesTo = ConvertTablesOptions.unformattedTable; importEndnotes = true; importFootnotes = true; importIndex = true; importTOC = true; importUnusedStyles = false; preserveGraphics = false; preserveLocalOverrides = false; preserveTrackChanges = false; removeFormatting = false; //resolveCharacterSytleClash and resolveParagraphStyleClash properties can be: //ResolveStyleClash.resolveClashAutoRename //ResolveStyleClash.resolveClashUseExisting //ResolveStyleClash.resolveClashUseNew resolveCharacterStyleClash = ResolveStyleClash.resolveClashUseExisting; resolveParagraphStyleClash = ResolveStyleClash.resolveClashUseExisting; useTypographersQuotes = true; }

The following script shows how to set Excel import preferences (for the complete script, see ExcelImportPreferences):
with(app.excelImportPreferences){ //alignmentStyle property can be: //AlignmentStyleOptions.centerAlign //AlignmentStyleOptions.leftAlign //AlignmentStyleOptions.rightAlign //AlignmentStyleOptions.spreadsheet alignmentStyle = AlignmentStyleOptions.spreadsheet; decimalPlaces = 4; preserveGraphics = false; //Enter the range you want to import as "start cell:end cell". rangeName = "A1:B16"; sheetIndex = 1; sheetName = "pathpoints"; showHiddenCells = false; //tableFormatting property can be: //TableFormattingOptions.excelFormattedTable //TableFormattingOptions.excelUnformattedTabbedText //TableFormattingOptions.excelUnformattedTable tableFormatting = TableFormattingOptions.excelFormattedTable; useTypographersQuotes = true; viewName = ""; }

CHAPTER 6: Text and Type

Exporting Text and Setting Text-Export Preferences

77

Exporting Text and Setting Text-Export Preferences
The following script shows how to export text from an InDesign document. Note that you must use text or story objects to export into text file formats; you cannot export all text in a document in one operation. (We omitted the myGetBounds function from this listing; you can find it in “Creating a text frame” on page 71,” or see the ExportTextFile tutorial script.)
var myDocument = app.documents.item(0); var myPage = myDocument.pages.item(0); var myTextFrame = myPage.textFrames.item(0); //Text exportFile method parameters: //Format as ExportFormat //To As File //[ShowingOptions As Boolean = False] //Format parameter can be: //ExportFormat.inCopy //ExportFormat.inCopyCS2Story //ExportFormat.rtf //ExportFormat.taggedText //ExportFormat.textType //Export the story as text. You'll have to fill in a valid file path on your system. myTextFrame.parentStory.exportFile(ExportFormat.textType, File("/c/test.txt"));

The following example shows how to export a specific range of text. (We omitted the myGetBounds function from this listing; you can find it in “Creating a text frame” on page 71,” or see the ExportTextRange tutorial script.)
var myDocument = app.documents.item(0); var myStory = myDocument.stories.item(0); var myStart = myStory.characters.item(0); var myEnd = myStory.paragraphs.item(0).characters.item(-1); myText = myStory.texts.itemByRange(myStart, myEnd); //Text exportFile method parameters: //Format as ExportFormat //To As File //[ShowingOptions As Boolean = False] //Format parameter can be: //ExportFormat.inCopy //ExportFormat.inCopyCS2Story //ExportFormat.rtf //ExportFormat.taggedText //ExportFormat.textType //Export the text range. You'll have to fill in a valid file path on your system. myText.exportFile(ExportFormat.textType, File("/c/test.txt"));

To specify the export options for the specific type of text file you’re exporting, use the corresponding export preferences object. The following script sets text-export preferences (for the complete script, see TextExportPreferences):
with(app.textExportPreferences){ //Options for characterSet: TextExportCharacterSet characterSet = TextExportCharacterSet.UTF8; //platform options: ImportPlatform platform = ImportPlatform.macintosh; }

The following script sets tagged text export preferences (for the complete script, see TaggedTextExportPreferences):

CHAPTER 6: Text and Type

Exporting Text and Setting Text-Export Preferences

78

with(app.taggedTextExportPreferences){ //Options for characterSet: //TagTextExportCharacterSet.ansi //TagTextExportCharacterSet.ascii //TagTextExportCharacterSet.gb18030 //TagTextExportCharacterSet.ksc5601 //TagTextExportCharacterSet.shiftJIS //TagTextExportCharacterSet.unicode characterSet = TagTextExportCharacterSet.unicode; //tagForm options: //TagTextForm.abbreviated //TagTextForm.verbose tagForm = TagTextForm.verbose; }

You cannot export all text in a document in one step. Instead, you need to either combine the text in the document into a single story and then export that story, or combine the text files by reading and writing files via scripting. The following script demonstrates the former approach. (We omitted the myGetBounds function from this listing; you can find it in “Creating a text frame” on page 71,” or see the ExportAllText tutorial script.) For any format other than text only, the latter method can become quite complex.
if(app.documents.length != 0){ if(app.documents.item(0).stories.length != 0){ myExportAllText(app.documents.item(0).name); } }

Here is the ExportAllText function referred to in the preceding fragment:
function myExportAllText(myDocumentName){ var myStory; //File name for the exported text. Fill in a valid file path on your system. var myFileName = "/c/test.txt"; //If you want to add a separator line between stories, set myAddSeparator to true. var myAddSeparator = true; var myNewDocument = app.documents.add(); var myDocument = app.documents.item(myDocumentName); var myTextFrame = myNewDocument.pages.item(0).textFrames.add( {geometricBounds:myGetBounds(myNewDocument, myNewDocument.pages.item(0))}); var myNewStory = myTextFrame.parentStory; for(myCounter = 0; myCounter < myDocument.stories.length; myCounter++){ myStory = myDocument.stories.item(myCounter); //Export the story as tagged text. myStory.exportFile(ExportFormat.taggedText, File(myFileName)); //Import (place) the file at the end of the temporary story. myNewStory.insertionPoints.item(-1).place(File(myFileName));

CHAPTER 6: Text and Type

Exporting Text and Setting Text-Export Preferences

79

//If the imported text did not end with a return, enter a return //to keep the stories from running together. if(myCounter != myDocument.stories.length -1){ if(myNewStory.characters.item(-1).contents != "\r"){ myNewStory.insertionPoints.item(-1).contents = "\r"; } if(myAddSeparator == true){ myNewStory.insertionPoints.item(-1).contents = "----------------------------------------\r"; } } } myNewStory.exportFile(ExportFormat.taggedText, File("/c/test.txt")); myNewDocument.close(SaveOptions.no); }

Do not assume that you are limited to exporting text using existing export filters. Because JavaScript can write text files to disk, you can have your script traverse the text in a document and export it in any order you like, using whatever text mark-up scheme you prefer. Here is a very simple example that shows how to export InDesign text as HTML. (We omitted the myGetBounds function from this listing; you can find it in “Creating a text frame” on page 71,” or see the ExportHTML tutorial script.)
var myStory, myParagraph, myString, myTag, myStartTag; var myEndTag, myTextStyleRange, myTable; //Use the myStyleToTagMapping array to set up your paragraph style to tag mapping. var myStyleToTagMapping = new Array; //For each style to tag mapping, add a new item to the array. myStyleToTagMapping.push(["body_text", "p"]); myStyleToTagMapping.push(["heading1", "h1"]); myStyleToTagMapping.push(["heading2", "h2"]); myStyleToTagMapping.push(["heading3", "h3"]); //End of style to tag mapping. if(app.documents.length !=0){ if(app.documents.item(0).stories.length != 0){ //Open a new text file. var myTextFile = File.saveDialog("Save HTML As", undefined); //If the user clicked the Cancel button, the result is null. if(myTextFile != null){ //Open the file with write access. myTextFile.open("w"); //Iterate through the stories. for(var myCounter = 0; myCounter < app.documents.item(0).stories.length; myCounter ++){ myStory = app.documents.item(0).stories.item(myCounter); for(var myParagraphCounter = 0; myParagraphCounter < myStory.paragraphs.length; myParagraphCounter ++){ myParagraph = myStory.paragraphs.item(myParagraphCounter); if(myParagraph.tables.length == 0){ if(myParagraph.textStyleRanges.length == 1){ //If the paragraph is a simple paragraph--no tables, no local //formatting--then simply export the text of the pararaph with //the appropriate tag. myTag = myFindTag(myParagraph.appliedParagraphStyle.name, myStyleToTagMapping); //If the tag comes back empty, map it to the //basic paragraph tag. if(myTag == ""){ myTag = "p"; } myStartTag = "<" + myTag + ">";

texts.texts.item(myColumnCounter). } myTextFile.write("\r").contents + . } else{ //Handle text style range export by iterating through the text //style ranges in the paragraph.characters. characters.itemByRange( myParagraph. and that the table is in the paragraph by itself).item(0).rows. cells. myTextFile.length. } switch(myTextStyleRange.item(-2)).texts.textStyleRanges.rows. } //Write the paragraphs' text to the text file.item(-1).characters. if(myTextStyleRange.item(myRowCounter). myTable = myParagraph. } else{ myString = "<td>" + myTable. for(var myColumnCounter = 0.length.columns.tables.texts. } else{ myString = myParagraph.fontStyle){ case "Bold": myString = "<b>" + myString + "</b>" break.myParagraph.textStyleRanges.contents.write(myString). for(var myRangeCounter = 0.contents.item(-2)).item(0). //omit the return character. myRangeCounter ++){ myTextStyleRange = myParagraph.contents. myColumnCounter++){ if(myRowCounter == 0){ myString = "<th>" + myTable.itemByRange( myTextStyleRange. } myTextFile. //If the paragraph is not the last paragraph in the story.cells.length. item(myColumnCounter). case "Italic": myString = "<i>" + myString + "</i>" break.rows. } } else{ //Handle table export (assumes that there is only one table per //paragraph. myRowCounter ++){ myTextFile. for(var myRowCounter = 0. myTextStyleRange. myRangeCounter < myParagraph..item(myRowCounter).contents + "</th>".characters. myRowCounter < myTable. myColumnCounter < myTable.writeln("<table border = 1>"). } else{ myString = myTextStyleRange.contents == "\r"){ myString = myParagraph.writeln(myStartTag + myString + myEndTag).characters.item(0).characters.item(-1)=="\r"){ myString = myTextStyleRange.contents.CHAPTER 6: Text and Type Exporting Text and Setting Text-Export Preferences 80 myEndTag = "</" + myTag + ">".item(0).item (myRangeCounter).writeln("<tr>"). myTextFile. if(myParagraph.item(1).

CHAPTER 6: Text and Type Understanding Text Objects 81 "</td>".close(). there are two main types of text object: layout objects (text frames) and text-stream objects (for example. characters. var myDone = false. break. } while((myDone == false)||(myCounter < myStyleToTagMapping.writeln(myString). stories. } myTextFile. } } } //Close the text file. As you can see.writeln("</table>"). myStyleToTagMapping){ var myTag = "". } myCounter ++. } myTextFile. myTextFile. do{ if(myStyleToTagMapping[myCounter][0] == myStyleName){ myTag = myStyleToTagMapping[myCounter][1].writeln("</tr>"). and words): . insertion points. } } } Here is the myFindTag function referred to in the above script: function myFindTag (myStyleName. } myTextFile.length)) return myTag. } Understanding Text Objects The following diagram shows a view of InDesign’s text object model. var myCounter = 0.

item(0) textFrames.item(0) characters.CHAPTER 6: Text and Type Understanding Text Objects 82 document story spread.item(0) textFrames.item(0) For any text stream object. . use the parentTextFrames property.item(0) characters. page.item(0) characters.item(0) stories.item(0) paragraphs. To get a reference to the text frame (or text frames) containing the text object.item(0) stories.item(0) characters. layer insertion points characters words lines paragraphs text columns text style ranges texts notes text containers text frame insertion points characters words lines paragraphs text columns text style ranges texts notes There are many ways to get a reference to a given text object. the parent of the object is the story containing the object.item(0) paragraphs. The following diagram shows a few ways to refer to the first character in the first text frame of the first page of a new document: document pages.

constructor. the parent of the text frame usually is the page or spread containing the text frame. } } Moving and copying text You can move a text object to another location in text using the move method. this script does not actually do anything. use the duplicate method (whose arguments are identical to the move method). see TextSelection). The following script fragment shows how it works (for the complete script. break."). see MoveText): . } } else{ alert("Please select some text and try again. Select some text and try again. get a reference to the //text in the text frame. default: alert("The selected object is not a text object. break. Unlike many of the other sample scripts.documents. Working with text selections Text-related scripts often act on a text selection. the parent of the text frame is the character containing the anchored frame. myProcessText(app.name){ case "InsertionPoint": case "Character": case "Word": case "TextStyleRange": case "Line": case "Paragraph": case "TextColumn": case "Text": case "Story": //The object is a text object. it simply presents a selection-filtering routine that you can use in your own scripts (for the complete script. switch (app. myProcessText(app. break.selection[0]. pass it on to a function. The following script demonstrates a way to determine whether the current selection is a text selection. To copy the text.length == 1){ //Evaluate the selection based on its type.selection[0]. If the text frame is inside a group or was pasted inside another page item.selection. if (app.item(0)).length != 0){ //If the selection contains more than one item. the parent of the text frame is the containing page item."). if (app.selection[0]). case "TextFrame": //If the selection is a text frame. the selection //is not text selected with the Type tool.CHAPTER 6: Text and Type Understanding Text Objects 83 For a text frame.texts. If the text frame was converted to an anchored frame. //In addition to checking for the above text objects. we can //also continue if the selection is a text frame selected with //the Selection tool or the Direct Selection tool.

paragraphs.item(0)). other approaches are faster.paragraphs. //This deletes the text from the source document.item(1).textFrames.after . var myTextFrameB = myPage.item(-1).add(). myTextFrameD.parentStory. //Create the target document.pages.item(0). you also can use the move method.textFrames.parentStory.item(3).documents. myTextFrameA.move(LocationOptions. mySoureParagraph. The following script shows how to move text from one document to another using move and duplicate. you can find it in “Creating a text frame” on page 71. myTargetTextFrame. Insert the source text before this paragraph. less fragile.item(0). you can find it in “Creating a text frame” on page 71.documents.add({geometricBounds:myGetBounds(mySourceDocument.item(0))."}). myTextFrameC.item(0).words.textFrames. use the following: //mySoureParagraph.pointSize = 24.paragraphs. myTextFrameB.item(0)) //Note that moving text removes it from its original location. mySourcePage). myTargetDocument.item(0). //To duplicate (rather than move) the text. var mySourcePage = mySourceDocument. You will need to select the text before you copy.item(0). (We omitted the myGetBounds function from this listing.documents. var myTargetTextFrame = myTargetPage.textFrames.item(0).parentStory. mySoureParagraph. and do not depend on the document being visible.words.CHAPTER 6: Text and Type Understanding Text Objects 84 var myDocument = app.pages.add(). var myTextFrameC = myPage.\rThis text is not the source text. //Move the text from the source document to the target document.befor e.item(-2).move(LocationOptions.” or see the MoveTextBetweenDocuments tutorial script.paragraphs. Using move or duplicate is much faster and more robust.paragraphs.item(-3). to use copy and paste.befor e. you should use copy and paste only as a last resort.parentStory. var myPage = myDocument.words.pages. var myTextFrameD = myPage. contents:"This is the source text. you can use the copy method of the application. var mySourceTextFrame = mySourcePage.words.duplicate(LocationOptions.AT_BEGINNING.words. myTextFrameD.item(0)) //Move WordA to before the word in TextFrameA.item(0). var myTargetPage = myTargetDocument. //Move WordC between the words in TextFrameC.textFrames.parentStory. contents:"This is the target text. var myTargetDocument = app.words.move(LocationOptions.add({geometricBounds:myGetBounds(myTargetDocument.parentStory. var mySoureParagraph = mySourceTextFrame. myTextFrameD. you must make the document visible and select the text you want to copy.item(0)).paragraphs. When you want to transfer formatted text from one document to another. var mySourceDocument = app.insertionPoints. Again.item(0).textFrames. (We omitted the myGetBounds function from this listing. When you need to copy and paste text.item(0).\r"}).move(LocationOptions.paragraphs.item(0).) //Create the source document.item(0).item(0).parentStory. Using the move or duplicate method is better than using copy and paste.pages.” or see the CopyPasteText tutorial script. var myTextFrameA = myPage. myTargetTextFrame.item(2).insertionPoints.) .AT_BEGINNING.item(1)) //Move WordB after the word in TextFrameB.

myTextFrameB. app. app.item(0). see CopyUnformattedText): var myDocument = app.textFrames. Text objects and iteration When your script moves.pages.contents = myTextFrameA. app. //Select the text.fontStyle = "Italic". var myPage = myDocument.textFrames. One way to copy unformatted text from one text object to another is to get the contents property of a text object. //Create a text frame on the active page.fontStyle = "Bold". app.documents. var myDocumentB = app. app.pages. 300.item(0).select(myTextFrameA.add({geometricBounds:myGetBounds(myDocumentA. it replicates the text string from one //text frame in another text frame): myTextFrameC. app.add({geometricBounds:myGetBounds(myDocumentB. var myTextFrameA = myPageA.item(0). //Make document A the active document.paste().documents.pages. app. 72.contents = "Text copied here will take on the formatting of the existing text.item(0).CHAPTER 6: Text and Type Understanding Text Objects 85 var myDocumentA = app.add({geometricBounds:[312. app. //Select the insertion point at which you want to paste the text.paste(). var myTextFrameB = myPage. app.texts.texts.parentStory.add({geometricBounds:[72.item(0). //Make document B the active document.textFrames.item(-1)). Text pasted here will retain its formatting.activeDocument = myDocumentA. myTextFrameA.select(myTextFrameA. myTextFrameB. 288]}).texts.) .fontStyle = "Italic".parentStory.contents = "This is the destination text frame.add(). myTextFrameA.copy(). var myTextFrameA = myPage. //Create another text frame on the active page. 72.parentStory.item(0)).\r". 288]}). deletes.item(0).” or see the TextIterationWrong tutorial script. var myTextFrameC = myPage.".insertionPoints.contents = "This is a formatted string.".item(0). 288]}). app.parentStory.".add(). myTextFrameC. var myPageB = myDocumentB. 144.item(-1).add({geometricBounds:[228.parentStory. myTextFrameC.texts. you can easily end up with invalid text references. var myString = "Example text.contents. var myPageA = myDocumentA. 444.textFrames. then use that string to set the contents property of another text object.copy().item(0)). you can find it in “Creating a text frame” on page 71. myPageB)}). //Copy from one frame to another using a simple copy.texts. //Copy the unformatted string from text frame A to the end of text frame C (note //that this doesn't really copy the text.textFrames.select(myTextFrameB.select(myTextFrameB.activeDocument = myDocumentB. 72.texts. contents:myString}). myPageA).item(0)). (We omitted the myGetBounds function from this listing. The following script demonstrates this problem. //Create another text frame on the active page. or adds text while iterating through a series of text objects.documents.parentStory. The following script shows how to do this (for the complete script.parentStory.item(0).insertionPoints.parentStory. var myTextFrameB = myPageB.insertionPoints.

stories. as shown in the following script fragment (for the complete script.words.item(0). var myStory = myDocument.” When the script deletes the second paragraph.paragraphs. see LinkTextFrames): .paragraphs. (We omitted the myGetBounds function from this listing. These properties correspond to the in port and out port on InDesign text frames. } } In the preceding example. as shown in the following script.documents. the third paragraph moves up to take its place.pointSize = 24. //The following for loop will fail to format all of the paragraphs. we focus on text frames.item(0). As it does so. var myStory = myDocument. some of the paragraphs are left unformatted.item(0).CHAPTER 6: Text and Type Working with Text Frames 86 var myDocument = app.words.documents.paragraphs.item(0).item(myParagraphCounter). the script processes the paragraph that had been the fourth paragraph in the story.remove(). } } Working with Text Frames In the previous sections of this chapter. for(var myParagraphCounter = 0. Linking text frames The nextTextFrame and previousTextFrame properties of a text frame are the keys to linking (or “threading”) text frames in InDesign scripting. it deletes paragraphs that begin with the word “Delete.item(0).paragraphs.item(myParagraphCounter).” or see the TextIterationRight tutorial script. When the loop counter reaches 2. in this section.stories. for(var myParagraphCounter = myStory.pointSize = 24.item(myParagraphCounter).item(myParagraphCounter). you can find it in “Creating a text frame” on page 71. myParagraphCounter ++){ if(myStory. } else{ myStory.paragraphs.length. } else{ myStory.paragraphs. myParagraphCounter < myStory.contents=="Delete"){ myStory. iterate backward through the text objects. the original third paragraph is now the second paragraph and is skipped. we concentrated on working with text stream objects.remove().item(myParagraphCounter). How does this happen? The loop in the script iterates through the paragraphs from the first paragraph in the story to the last.length-1. //The following for loop will format all of the paragraphs by iterating //backwards through the paragraphs in the story. myParagraphCounter >= 0.item(0). To avoid this problem.paragraphs. the page-layout items that contain text in an InDesign document.paragraphs. myParagraphCounter --){ if(myStory.item(myParagraphCounter).contents=="Delete"){ myStory.) var myDocument = app.

length != 0){ //Process the objects in the selection to create a list of //qualifying objects (text frames).add().item(0).selection.item(0).item(1). then get the parent text frame. break. see BreakFrame): var myObjectList = new Array. if(app.previousTextFrame = myTextFrameB.item(0).CHAPTER 6: Text and Type Working with Text Frames 87 var myDocument = app. switch(app. myTextFrameA.pages.selection. //Link TextFrameC to TextFrameB using the previousTextFrame property. var myPage = myDocument. myTextFrameA. for(myCounter = 0.documents. Removing a frame from a story In InDesign. Unlinking text frames The following example script shows how to unlink text frames (for the complete script. var myTextFrameC = myNewPage. var myTextFrameA = myPage.documents. //Add a page.pages. myCounter ++){ switch(app. default: if(app. var myTextFrameB = myPage.placeholderText. myTextFrameC.nextTextFrame = myTextFrameB.textFrames.name){ case "TextFrame": myObjectList.textFrames. //Script does nothing if no documents are open or if no objects are selected.constructor. myTextFrameA.contents = TextFrameContents.selection.length != 0){ if(app. 72.selection[myCounter].add({geometricBounds:[72.selection[myCounter].constructor.selection[myCounter]).name){ case "Text": case "InsertionPoint": case "Character": case "Word": case "Line": case "TextStyleRange": case "Paragraph": case "TextColumn": . see UnlinkTextFrames): //Unlink the two text frames.length. //Create another text frame on the new page. 144. 144]}) //Link TextFrameA to TextFrameB using the nextTextFrame property.push(app. //Fill the text frames with placeholder text.textFrames. myCounter < app.length == 1){ //If text is selected. var myNewPage = myDocument.nothing. deleting a frame from a story does not delete the text in the frame. unless the frame is the only frame in the story. The following script fragment shows how to delete a frame and the text it contains from a story without disturbing the other frames in the story (for the complete script.nextTextFrame = NothingEnum.

id. myCounter<myNewLength.duplicate().contents != ""){ myTextFrame.nextTextFrame != null)&&(myTextFrame.textFrameIndex. if(myObjectList.push(app.id.id. $. 8))){ return -1. 8)). } . } } //If the object list is not empty. 8)). if(myTextFrame. break. $.textFrameIndex. for (var myCounter = 0. } } break.texts. } } } Here is the myBreakFrames function referred to in the preceding script.length. 8)+myPadString(b.previousTextFrame != null)){ var myNewFrame = myTextFrame.CHAPTER 6: Text and Type Working with Text Frames 88 myObjectList. var myNewLength = myLength-String(myString).item(0).length != 0){ myBreakFrames(myObjectList). myCounter++) { myTempString += "0".write("padded a: " + myPadString(a. function myBreakFrames(myObjectList){ myObjectList. myLength) { var myTempString = "". 8)+myPadString(b.8)+myPadString(b. pass it on to the function //that does the real work. myCounter ++){ myBreakFrame(myObjectList[myCounter]). myCounter < myObjectList. } return myTempString + myString.8)+myPadString(a.length. } return 0. } } function myBreakFrame(myTextFrame){ if((myTextFrame.id.remove(). 8)+myPadString(a.write("padded b: " + myPadString(b. 8)) > (myPadString(b. for(var myCounter = 0.remove().8)) < (myPadString(b. } function myPadString(myString.id. parentTextFrames[0]).8))){ return 1.id. } myTextFrame.textFrameIndex. we can sort the text frames //into the right (reverse) order in a single pass. } if((myPadString(a. } } function myReverseSortByTextFrameIndex(a.textFrameIndex.b){ //By combining the story id with the text frame index. if((myPadString(a. 8)+myPadString(a.sort(myReverseSortByTextFrameIndex).textFrameIndex.textFrameIndex.selection[myCounter].

mySplitStory(mySelection. //Process the selection.duplicate().parentStory. var mySelection = app. or graphic line) at a specific location in text (usually an insertion point). for(var myCounter = myStory. myTextFrame. see SplitStory): if(app. do nothing. myCounter >= 0. polygon. } } } Here is the mySplitStory function referred to in the preceding script: function mySplitStory(myStory){ var myTextFrame. independent stories. for(var myCounter = myStory.remove().length-1.selection. //Duplicate each text frame in the story. do something.textContainers. otherwise. do nothing.constructor. } } Creating an anchored frame To create an anchored frame (also known as an inline frame). see AnchoredFrame): .CHAPTER 6: Text and Type Working with Text Frames 89 Splitting all frames in a story The following script fragment shows how to split all frames in a story into separate.parentStory).length != 1){ //Splitting the story is a two-step process: first. The following script fragment shows an example (for the complete script. } } function myRemoveFrames(myStory){ //Remove each text frame in the story. each containing one unlinked text frame (for the complete script.documents.length-1.selection[0]. oval. myCounter --){ myTextFrame = myStory. delete the original text frames.length != 0){ //Get the first item in the selection. you can create a text frame (or rectangle.textContainers. duplicate //the text frames. If text or a text frame is //selected.parentStory).name){ case "Text": case "InsertionPoint": case "Character": case "Word": case "Line": case "TextStyleRange": case "Paragraph": case "TextColumn": case "TextFrame": //If the text frame is the only text frame in the story. myRemoveFrames(mySelection.textContainers[myCounter]. if(mySelection. second.textContainers. } break. Iterate backwards to //avoid invalid references.textContainers[myCounter]. myCounter --){ myStory. myCounter >= 0. switch(mySelection.length != 0){ if(app.

verticalReferencePoint = VerticallyRelativeTo.textFrames. myBounds[1]+72]. myBounds[1]+72]. myInsertionPoint = myTextFrame.CHAPTER 6: Text and Type Formatting Text 90 var myInsertionPoint = myTextFrame.anchored. //Recompose the text to make sure that getting the //geometric bounds of the inline graphic will work. //Set the width and height of the inline frame.) . myBounds[0]+24.item(0).item(0). we'll //make the frame 24 points tall by 72 points wide. //Recompose the text to make sure that getting the //geometric bounds of the inline graphic will work. In this example. } Formatting Text In the previous sections of this chapter. anchorSpaceAbove = 24. Setting text defaults You can set text defaults for both the application and each document. (For the complete script. myArray = [myBounds[0]. horizontalReferencePoint = AnchoredRelativeTo. var myArray = [myBounds[0]. myTextFrame.contents = "This is an inline frame.add(). linked text frames. var myInlineFrame = myInsertionPoint.recompose. myAnchoredFrame.".geometricBounds = myArray. anchorXoffset = 72.item(0).geometricBounds = myArray. var myBounds = myInlineFrame.textFrames.".anchoredObjectSettings){ anchoredPosition = AnchorPosition. with(myAnchoredFrame. myTextFrame. myAnchoredFrame. var myBounds = myAnchoredFrame.geometricBounds. Text defaults for the application determine the text defaults in all new documents. //Get the geometric bounds of the inline frame. we apply formatting to text. myInlineFrame. myBounds[0]+24. //Set the width and height of the inline frame.recompose. horizontalAlignment = HorizontalAlignment. we'll //make the frame 24 points tall by 72 points wide.item(0).add(). anchorPoint = AnchorPoint.item(0).geometricBounds. var myAnchoredFrame = myInsertionPoint. In this section.paragraphs. and worked with stories and text objects. myInlineFrame. All the typesetting capabilities of InDesign are available to scripting. we added text to a document.lineBaseline. text defaults for a document set the formatting of all new text objects in that document.insertionPoints.paragraphs.texts.item(1). In this example. //Get the geometric bounds of the inline frame.texts. anchorYoffset = 24.anchorLocation.contents = "This is an anchored frame. see TextDefaults. myBounds[1].insertionPoints.leftAlign. myBounds[1].topLeftAnchor.

hyphenateLadderLimit = 1.characterStyles. replace the variable "myDocument" //with "app" in the following lines. Fill in the //name of a font on your system. dropCapCharacters = 0.catch structure. keepFirstLines = 2.. with(myDocument. hyphenateAfterFirst = 3. gridAlignFirstLineOnly = false. keepLastLines = 2. } catch(e){} //Because the language might not be available.item(0). } catch(e){} //Because the font style might not be available. keepLinesTogether = true.item("Black").catch structure. kerningMethod = "Optical". //Assumes that the application has a default character style named "myDropCap" dropCapStyle = myDocument.. justification = Justification. desiredGlyphScaling = 100.normal. it's usually best //to apply the language within a try. composer = "Adobe Paragraph Composer".documents.catch structure.colors. hyphenateBeforeLast = 4. try{ appliedFont = app. keepWithNext = 0.textDefaults){ alignToBaseline = true. kerningValue = 0. fillTint = 100. keepAllLinesTogether = false. baselineShift = 0. hyphenateCapitalizedWords = false. } fillColor = myDocument.item("Minion Pro"). hyphenation = true.. capitalization = Capitalization. hyphenationZone = 36. balanceRaggedLines = false. horizontalScale = 100. it's usually best //to apply the font within a try.leftAlign. it's usually best //to apply the font style within a try.CHAPTER 6: Text and Type Formatting Text 91 var myDocument = app. hyphenWeight = 9.fonts. desiredWordSpacing = 100. //To set the application text formatting defaults. try{ appliedLanguage = "English: USA"... try{ fontStyle = "Regular". firstLineIndent = 14. desiredLetterSpacing = 0.. . if(dropCapCharacters != 0){ dropCapLines = 3.item("myDropCap"). } catch(e){} autoLeading = 100. hyphenateWordsLongerThan = 5. //Because the font might not be available. leading = 14.

pointSize = 11. spaceAfter = 0. otfTitling = false.columnWidth. ruleAboveTint = 100. ruleBelowGapOverprint = false. ruleAboveLineWeight = . noBreak = false.item("Black").item("Solid"). maximumWordSpacing = 160. maximumGlyphScaling = 100. ruleAboveType = myDocument.swatches. minimumGlyphScaling = 100. otfSlashedZero = false. if(ruleBelow == true){ ruleBelowColor = myDocument. ruleBelowOverprint = false. ruleAboveWidth = RuleWidth. ruleAbove = false. ruleBelowGapTint = 100. ruleAboveGapTint = 100. ruleBelowType = app. otfFigureStyle = OTFFigureStyle. otfContextualAlternate = true.colors. ruleBelowLeftIndent = 0.swatches.25. ruleBelowWidth = RuleWidth. minimumLetterSpacing = 0.item("None"). ruleAboveOverprint = false. position = Position. ruleAboveOffset = 14. overprintFill = false.25. if(strikeThru == true){ .item("Black"). overprintStroke = false. ruleBelowLineWeight = . otfSwash = false. otfFraction = true.item("Solid").CHAPTER 6: Text and Type Formatting Text 92 leftIndent = 0. otfDiscretionaryLigature = false. if(ruleAbove == true){ ruleAboveColor = myDocument.anywhere.proportionalOldstyle. ruleBelowTint = 100.leftAlign. otfHistorical = false.columnWidth. spaceBefore = 0. ruleAboveGapColor = myDocument. otfOrdinal = false. ruleBelowRightIndent = 0.strokeStyles. } singleWordJustification = SingleWordJustification. maximumLetterSpacing = 0. ligatures = true. ruleAboveLeftIndent = 0. startParagraph = StartParagraph. ruleBelowOffset = 0.normal. minimumWordSpacing = 80.colors. ruleBelowGapColor = myDocument. ruleAboveRightIndent = 0. rightIndent = 0. ruleAboveGapOverprint = false. strikeThru = false. skew = 0.strokeStyles.item("None"). } ruleBelow = false.

item("None"). strikeThroughTint = 100. if(underline == true){ underlineColor = myDocument.item("Black").name.colors. by contrast.) var myApplicationFonts = app. underlineGapTint = 100. var myString = "Document Fonts:\r". underlineOverprint = false. underlineWeight = .fonts.swatches.length.myCounter<myDocumentFontNames. strokeTint = 100.fonts. NOTE: Font names typically are of the form familyName<tab>fontStyle.length.everyItem().fonts.myCounter<myFontNames. } strokeColor = myDocument.name. strikeThroughOverprint = false.item(0). underlineTint = 100. } myStory. myCounter++){ myString += myDocumentFontNames[myCounter] + "\r". } myString += "\rApplication Fonts:\r". var myDocumentFonts = myDocument. where familyName is the name of the font family. underlineGapColor = myDocument.stories. For example: "Adobe Caslon Pro<tab>Semibold Italic" .item("Black"). strikeThroughGapTint = 100. for(var myCounter = 0. var myDocumentFontNames = myDocument. strikeThroughGapColor = myDocument. for(var myCounter = 0.item("None").25. contains only those fonts used in the document. strikeThroughWeight = . var myStory = myDocument. strikeThroughGapOverprint = false. strikeThroughOffset = 3. The following script shows the difference between application fonts and document fonts.colors. underlineType = myDocument. myCounter++){ myString += myFontNames[myCounter] + "\r".CHAPTER 6: Text and Type Formatting Text 93 strikeThroughColor = myDocument. underlineOffset = 3. The fonts collection of a document.documents.contents = myString.swatches.25 } verticalScale = 100.everyItem(). tracking = 0. var myFontNames = myApplicationFonts. strikeThroughType = myDocument.strokeStyles. var myDocument = app. <tab> is a tab character.strokeStyles.item(0).swatches. for the complete script. (We omitted the myGetBounds function here. and fontStyle is the name of the font style. see FontCollections.item("Solid").item("Solid"). The fonts collection of a document also contains any missing fonts—fonts used in the document that are not accessible to InDesign. } Working with fonts The fonts collection of the InDesign application object contains all fonts accessible to InDesign. underlineGapOverprint = false.item("None"). underline = false. strokeWeight = 0.

fillTint = -1.bulletsTextAfter = "^t". myTextObject.colors.numberingLists. var myPage = myDocument.firstLineIndent = 0.parentStory.appliedNumberingList = myDocument. as shown in the following script fragment (from the ApplyFont tutorial script): //Given a font name "myFontName" and a text object "myText".appliedFont = app.. myTextObject.appliedFont = app.item("[No Paragraph Style]"). Changing text properties Text objects in InDesign have literally dozens of properties corresponding to their formatting attributes.leftAlign. myTextObject.item(0). use the appliedFont property. . myTextObject. myTextObject. myTextObject.noBalancing.dropCapLines = 0. myTextObject. as shown in the following script fragment: myText. myTextObject. myTextFrame. myTextObject.baselineShift = 0.item("Black"). myTextObject..appliedParagraphStyle = myDocument.appliedLanguage = app.composer = "Adobe Paragraph Composer".item("Minion ProRegular").gradientStrokeLength = -1. myTextObject. myTextObject.dropCapCharacters = 0.item("[Default]").fonts.dropCapStyle = myDocument.contents = "x".appliedCharacterStyle = myDocument. myTextObject. myText.desiredLetterSpacing = 0.pages. myTextObject.fillColor = myDocument.item(0).alignToBaseline = false.item("[None]"). The SetTextProperties tutorial script shows how to set every property of a text object. myTextObject.item("English: USA").characterStyles.characterStyles.fonts.appliedFont = app. myTextObject. myTextObject.desiredWordSpacing = 100. var myTextObject = myTextFrame.item("[None]").characterStyles.noList.documents.gradientFillLength = -1. myTextObject. A fragment of the script is shown below: var myDocument = app.gradientFillStart = [0.dropcapDetail = 0.item(0). myTextObject. Even one insertion point features properties that affect the formatting of text—up to and including properties of the paragraph containing the insertion point. myText. myTextObject.normal.gradientFillAngle = 0.0].textFrames. myTextObject. var myTextFrame = myPage.add(). You also can apply a font by specifying the font family name and font style.gradientStrokeAngle = 0.item(myFontName). myTextObject. myTextObject.CHAPTER 6: Text and Type Formatting Text 94 Applying a font To apply a local font change to a range of text.balanceRaggedLines = BalanceLinesStyle. myTextObject.fontStyle = "Semibold Italic". myTextObject.bulletsAndNumberingListType = ListType. myTextObject.capitalization = Capitalization. myTextObject. myTextObject.desiredGlyphScaling = 100.bulletsAlignment = ListAlignment.item("[None]").fontStyle = "Regular".paragraphStyles.languagesWithVendors. myTextObject.autoLeading = 120.bulletsCharacterStyle = myDocument.characters. myTextObject.item("Adobe Caslon Pro").fonts. myTextObject.

myTextObject.minimumGlyphScaling = 100.numberingApplyRestartPolicy = true. myTextObject.lastLineIndent = 0. myTextObject.minimumWordSpacing = 80.leftAlign.keepAllLinesTogether = false..hyphenateAcrossColumns = true.keepLastLines = 2. myTextObject. myTextObject.position = Position. myTextObject. myTextObject. myTextObject. myTextObject.0].positionalForm = PositionalForms.hyphenationZone = 3. myTextObject. myTextObject. myTextObject. myTextObject. myTextObject. myTextObject.gradientStrokeStart = [0.otfSwash = false. myTextObject. myTextObject.^t".maximumGlyphScaling = 100. myTextObject. .otfMark = true. myTextObject. myTextObject. myTextObject.kerningMethod = "Optical". myTextObject.proportionalLining.rightIndent = 0.leading = 12.otfLocale = true.numberingFormat = "1.keepFirstLines = 2. myTextObject.numberingAlignment = ListAlignment. myTextObject.item("[None]").leftAlign.hyphenWeight = 5. myTextObject. myTextObject. myTextObject. myTextObject. 4.otfFraction = false. myTextObject. myTextObject.pointSize = 12. myTextObject.overprintStroke = false.keepLinesTogether = false. myTextObject. myTextObject.horizontalScale = 100. 3.maximumWordSpacing = 133. myTextObject.numberingExpression = "^#. myTextObject. myTextObject.overprintFill = false.otfSlashedZero = false. myTextObject. myTextObject.numberingCharacterStyle = myDocument.keepRuleAboveInFrame = false.otfStylisticSets = 0.normal.otfHistorical = false.numberingContinue = true. myTextObject. myTextObject.hyphenateLadderLimit = 3. myTextObject.none.maximumLetterSpacing = 0. //myTextObject.gridAlignFirstLineOnly = false.". myTextObject. myTextObject.hyphenateCapitalizedWords = true.ligatures = true. myTextObject.hyphenateWordsLongerThan = 5.leftIndent = 0.otfOrdinal = false. myTextObject.otfTitling = false..numberingStartAt = 1.hyphenation = true. myTextObject. myTextObject. myTextObject.keepWithNext = 0. 2.otfContextualAlternate = true. myTextObject.hyphenateAfterFirst = 2.otfDiscretionaryLigature = false. myTextObject. myTextObject.hyphenateBeforeLast = 2. myTextObject. myTextObject.characterStyles. myTextObject. myTextObject.kerningValue = error.hyphenateLastWord = true.noBreak = false.minimumLetterSpacing = 0.numberingLevel = 1.CHAPTER 6: Text and Type Formatting Text 95 myTextObject. myTextObject. myTextObject.ignoreEdgeAlignment = false.otfFigureStyle = OTFFigureStyle. myTextObject.justification = Justification.

item("Solid").swatches.columnWidth. myTextObject. myTextObject. myTextObject.singleWordJustification = 1718971500. myTextObject.strikeThroughWeight = -9999.ruleBelowLeftIndent = 0.ruleAboveOverprint = false. myTextObject.strokeStyles.swatches.strikeThroughGapOverprint = false. myTextObject.item("Solid").item("None").ruleAboveTint = -1. myTextObject. myTextObject.ruleAboveOffset = 0. myTextObject.strikeThroughGapColor = myDocument. myTextObject. myTextObject.startParagraph = 1851945579.ruleAboveRightIndent = 0. myTextObject.ruleBelowType = myDocument. myTextObject.ruleBelowWidth = RuleWidth. .strikeThroughColor = "Text Color". myTextObject.ruleAbove = false. myTextObject. myTextObject. myTextObject. myTextObject.ruleBelowLineWeight = 1. myTextObject.underlineWeight = -9999.item("Solid").ruleAboveWidth = RuleWidth. myTextObject.skew = 0. myTextObject. myTextObject. myTextObject.spaceBefore = 0. myTextObject.ruleBelowOverprint = false.strikeThroughOverprint = false. myTextObject.ruleAboveGapColor = myDocument. myTextObject. myTextObject.strokeStyles. myTextObject.ruleBelowGapColor = myDocument.item("None").tracking = 0.ruleAboveType = myDocument.ruleBelow = false.strokeWeight = 1.underlineGapTint = -1.strokeColor = myDocument. myTextObject. myTextObject. myTextObject. myTextObject.item("None").underline = false.underlineTint = -1. myTextObject. myTextObject.underlineOverprint = false. myTextObject.underlineGapColor = myDocument.item("Solid").strikeThru = false.ruleAboveLineWeight = 1.columnWidth. myTextObject.ruleBelowGapTint = -1. myTextObject. myTextObject. myTextObject.underlineOffset = -9999. myTextObject. myTextObject.ruleBelowGapOverprint = false.ruleAboveGapTint = -1.swatches.ruleAboveColor = "Text Color". myTextObject.strokeStyles. myTextObject. myTextObject.ruleAboveLeftIndent = 0.CHAPTER 6: Text and Type Formatting Text 96 myTextObject.ruleAboveGapOverprint = false.strokeStyles.underlineColor = "Text Color". myTextObject. myTextObject.spaceAfter = 0.ruleBelowRightIndent = 0.ruleBelowColor = "Text Color".strikeThroughType = myDocument. myTextObject.swatches.underlineGapOverprint = false.item("None").underlineType = myDocument.ruleBelowTint = -1.item("None"). myTextObject.strikeThroughOffset = -9999.swatches.ruleBelowOffset = 0.strokeTint = -1. myTextObject.strikeThroughGapTint = -1. myTextObject. myTextObject. myTextObject. myTextObject.strikeThroughTint = -1.verticalScale = 100. myTextObject. myTextObject.

parentStory. } catch (myError){ //The color style did not exist. Creating and applying styles While you can use scripting to apply local formatting—as in some of the examples earlier in this chapter—you probably will want to use character and paragraph styles to format your text.justification = Justification. myColorA = myDocument. myText.process.geometricBounds = myGetBounds(myDocument. myName = myColorB. 0. which makes it easier to redefine the style. //Access the active document and page. //Enter text in the text frame. myText. myText. collect the text formatted with a given style.CHAPTER 6: Text and Type Formatting Text 97 Changing text color You can apply colors to the fill and stroke of text characters.contents = "Text\rColor" var myText = myTextFrame. so create it. //If the color does not exist. 0]}). myName = myColorA. as shown in the following script fragment (from the TextColors tutorial script): var myColorA.item("DGC1_664b").pointSize = 72. or find and/or change the text. //Apply a color to the fill of the text. myName. myText.fillColor = myColorB.colors. trying to get its name will generate an error. try{ myColorA = myDocument.strokeWeight = 3. myTextFrame.add({name:"DGC1_664a". var myPage = app.name.colors.pointSize = 144. var myTextFrame = myPage.textFrames.fillColor = myColorA.paragraphs. //Use the itemByRange method to apply the color to the stroke of the text. colorValue:[70. 50]}). myTextFrame. //If the color does not exist. var myText = myTextFrame.activeDocument.strokeColor = myColorB. myPage).colors.paragraphs.item(0) myText. myColorB = myDocument. myText. try{ myColorB = myDocument. } //Create a text frame on the active page.strokeWeight = 3. Using styles creates a link between the formatted text and the style. } catch (myError){ //The color style did not exist. //Create a color.add({name:"DGC1_664b".justification = Justification. myText. model:ColorModel. trying to get its name will generate an error. colorValue:[90.item(1) myText. so create it. myText. 100. } //Create another color. model:ColorModel.strokeColor = myColorA.centerAlign. 70.process.activePage.parentStory.add(). myColorB. var myDocument = app.item("DGC1_664a").colors.activeWindow. //Set the bounds of the text frame.centerAlign. 30. Paragraph and character styles are . myText.name.

trying to get its name will generate an error.fillColor = myColor.documents.item("Red").characters.texts. var myTextFrame = myPage. myName = myCharacterStyle. try{ myCharacterStyle = myDocument. The following example script fragment shows how to create and apply paragraph and character styles (for the complete script.characters.applyParagraphStyle(myParagraphStyle.geometricBounds = myGetBounds(myDocument. colorValue:[0. //If the style does not exist.add({name:"myParagraphStyle"}). } catch (myError){ //The style did not exist.item(0). trying to get its name will generate an error. var myPage = myDocument. //If the color does not exist.parentStory. myTextFrame. which you can now use to specify formatting. model:ColorModel. } catch (myError){ //The paragraph style did not exist. } //Create a text frame on the active page. myPage).add({name:"Red". trying to get its name will generate an error. try{ myParagraphStyle = myDocument.colors. the variable myCharacterStyle contains a reference to a character //style object. true).applyParagraphStyle(myParagraphStyle. 0]}). myColor = myDocument. 100. myTextFrame. } //At this point. so create it.characterStyles.CHAPTER 6: Text and Type Formatting Text 98 the keys to text formatting productivity and should be a central part of any script that applies text formatting.paragraphStyles. //If the paragraph style does not exist.name.parentStory.process. //Set the bounds of the text frame. 100.colors.item("myCharacterStyle").contents = "Normal text. var myEndCharacter = myTextFrame. the variable myParagraphStyle contains a reference to a paragraph //style object. see CreateStyles): var myDocument = app.name.itemByRange(myStartCharacter.item("myParagraphStyle"). var myStartCharacter = myTextFrame. myEndCharacter).characterStyles.add({name:"myCharacterStyle"}).texts. so create it. which you can now use to specify formatting.parentStory.item(13). so create it. myTextFrame. More normal text.add().pages. . myCharacterStyle. Text with a character style applied to it.item(0). myParagraphStyle = myDocument. //Create a color for use by one of the paragraph styles we'll create. true).paragraphStyles. myName = myColor.item(0). myCharacterStyle = myDocument. //Create a paragraph style named "myParagraphStyle" if //no style by that name already exists.textFrames. //Fill the text frame with placeholder text. myTextFrame.".item(54).parentStory. myName = myParagraphStyle. //Create a character style named "myCharacterStyle" if //no style by that name already exists. try{ myColor = myDocument. } //At this point.name. } catch (myError){ //The color style did not exist.

textStylesFormat. true).parentStory. as shown in the following script fragment (from the ImportTextStyles tutorial script): //Create a new document.importStyles(ImportFormat. var myStartCharacter = myTextFrame.documents.itemByRange(myStartCharacter. var myTextFrame = myPage.characters.remove(myDocument.textFrames. Options are: // GlobalClashResolutionStrategy.paragraphStyles.item(0). //importStyles parameters: // Format as ImportFormat enumeration. repetition:1}). var myPage = myDocument. delimiter:". Nested styles apply character-style formatting to a paragraph according to a pattern. .characters.paragraphStyles. Why check for the existence of a style when creating a new document? It always is possible that the style exists as an application default style.nestedStyles.add().CHAPTER 6: Text and Type Formatting Text 99 Why use the applyParagraphStyle method instead of setting the appliedParagraphStyle property of the text object? The applyParagraphStyle method gives the ability to override existing formatting.item(0).loadAllWithOverwrite // GlobalClashResolutionStrategy. trying to create a new style with the same name results in an error. setting the property to a style retains local formatting. //(Note that the story object does not have the applyParagraphStyle method. Importing paragraph and character styles You can import character and paragraph styles from other InDesign documents.texts. If it does.loadAllWithOverwrite).item("myParagraphStyle").add({appliedCharacterStyle:myCharacterStyle. myDocument = app.textStylesFormat // From as File // GlobalStrategy as GlobalClashResolutionStrategy enumeration. you can choose the way you want to format any text tagged with that style.". InDesign scripting works the same way. The following script fragment shows how to create a paragraph style containing nested styles (for the complete script. myEndCharacter).paragraphStylesFormat // ImportFormat. see NestedStyles): var myDocument = app. myParagraphStyleA.item(0). var myParagraphStyleA = myDocument. Options for text styles are: // ImportFormat. //Use the itemByRange method to apply the paragraph to all of the text in the story.activeDocument.loadAllWithRename myDocument.doNotLoadTheStyle // GlobalClashResolutionStrategy. //Remove the paragraph style myParagraphStyleA and replace with myParagraphStyleB. var myNestedStyle = myParagraphStyle. var myEndCharacter = myTextFrame.parentStory.) myTextFrame.item("myParagraphStyleA").pages.indd"). var myParagraphStyle = myDocument.item(0). inclusive:true. File("/c/styles.item(-1).applyParagraphStyle(myParagraphStyle.paragraphStyles. Deleting a style When you delete a style using the user interface. as shown in the following script fragment (from the RemoveStyle tutorial script): var myDocument = app.documents.characterStylesFormat // ImportFormat.parentStory. GlobalClashResolutionStrategy.item("myParagraphStyleB")). //Import the styles from the saved document.

CHAPTER 6: Text and Type Finding and Changing Text 100 Finding and Changing Text The find/change feature is one of the most powerful InDesign tools for working with text.nothing. and scripts can use find/change to go far beyond what can be done using the InDesign user interface. About find/change preferences Before you search for text.findTextPreferences = NothingEnum. app. or glyph you want to find and/or change.nothing. or “grep. you might face the problem of invalid text references. 3. InDesign has three ways of searching for text: You can find text and/or text formatting and change it to other text and/or text formatting. 2. //find/change grep preferences app. All the find/change methods take one optional parameter. ReverseOrder. to make sure the settings from previous searches have no effect on your search. Depending on the type of find/change operation. formatting. Clear the find/change preferences. A typical find/change operation involves the following steps: 1.” This type of find/change operation uses the findGrepPreferences and changeGrepPreferences objects to specify parameters for the findGrep and changeGrep methods.nothing. If you are processing the results of a find or change operation in a way that adds or removes text from a story.nothing. Clear find/change preferences again. Execute the find/change operation. 4. or you can have the search operation return the results in reverse order and then iterate through the collection normally. as discussed earlier in this chapter.changeTextPreferences = NothingEnum. //find/change glyph preferences app.changeGlyphPreferences = NothingEnum. This type of find/change operation uses the findGlyphPreferences and changeGlyphPreferences objects to specify parameters for the findGlyph and changeGlyph methods. .nothing.nothing. You also need to set some find/change preferences to specify the text. which specifies the order in which the results of the search are returned. you probably will want to clear find and change preferences. It is fully supported by scripting.changeGrepPreferences = NothingEnum. app. You can find specific glyphs (and their formatting) and replace them with other glyphs and formatting. you can either construct your loops to iterate backward through the collection of returned text objects.findGrepPreferences = NothingEnum. You can find text using regular expressions.findGlyphPreferences = NothingEnum. this can take one of the following three forms: //find/change text preferences app. regular expression. app. Set up search parameters. In this case. This type of find/change operation uses the findTextPreferences and changeTextPreferences objects to specify parameters for the findText and changeText methods.

includeLockedStoriesForFind = false. app. app.changeText().includeFootnotes = false. text frames.findChangeTextOptions.findChangeTextOptions.activeDocument.wholeWord = false.changeTextPreferences = NothingEnum.caseSensitive = false.includeLockedStoriesForFind = false.includeLockedLayersForFind = false. app. app.length + " instances of the search string.findChangeTextOptions. myDocument. text columns.includeLockedLayersForFind = false.findTextPreferences = NothingEnum.nothing.findChangeTextOptions.findChangeTextOptions.findWhat = "copy". //Search the document for the string "Text". see ChangeText): var myDocument = app. //Set the find options.findTextPreferences = NothingEnum. app.nothing.changeTextPreferences = NothingEnum.findText(). The findText method and its parameters are the same for all text objects. //Clear the find/change text preferences after the search.findChangeTextOptions.findChangeTextOptions. //Clear the find/change text preferences.findChangeTextOptions.findChangeTextOptions.includeMasterPages = false.caseSensitive = false. app. you set other properties of the findTextPreferences and changeTextPreferences objects. app. app.includeFootnotes = false. app. app.findChangeTextOptions. alert("Found " + myFoundItems.wholeWord = false.changeTo = "text".nothing. app.changeTextPreferences. you also can search stories. app.changeTextPreferences = NothingEnum.findChangeTextOptions. app.").activeDocument.includeHiddenLayers = false. var myFoundItems = myDocument. or any other text object. app. (For the complete script.includeHiddenLayers = false. //Search the document for the string "copy" and change it to "text".findTextPreferences. paragraphs. app.findChangeTextOptions.findTextPreferences = NothingEnum. app. //Set the find options.nothing. While the following script fragment searches the entire document.changeTextPreferences = NothingEnum. app. Finding and changing text formatting To find and change text formatting.CHAPTER 6: Text and Type Finding and Changing Text 101 Finding and changing text The following script fragment shows how to find a specified string of text. as shown in the script fragment below (from the FindChangeFormatting tutorial script): . The following script fragment shows how to find a specified string of text and replace it with a different string (for the complete script.nothing. app.includeMasterPages = false. app.nothing.nothing. //Clear the find/change text preferences. app. app.) var myDocument = app.findTextPreferences. app.findWhat = "text". app.findTextPreferences = NothingEnum. app.findChangeTextOptions.findChangeTextOptions. see FindText. app.nothing.

Regular-expression find/change also can find text with a specified format or replace the formatting of the text with formatting specified in the properties of the changeGrepPreferences object. app. myDocument. app. //Apply the change to 24-point text only. myDocument.includeMasterPages = false. app.nothing. app.pointSize = 10. app.findChangeTextOptions.findChangeTextOptions.caseSensitive = false.findChangeTextOptions.findChangeGrepOptions.findChangeGrepOptions..documents. app.findGrepPreferences.findGrepPreferences = NothingEnum.nothing.includeMasterPages = false. The following script fragment shows how to use these methods and the related preferences objects (for the complete script. In a text file marked up using this scheme. app.includeHiddenLayers = false.includeHiddenLayers = false.findTextPreferences = NothingEnum. PageMaker paragraph tags (which are not the same as PageMaker tagged-text format files) are an example of a simplified text mark-up scheme. app. paragraph style names appear at the start of a paragraph.underline = true.nothing.findChangeGrepOptions. One handy use for grep find/change is to convert text mark-up (i. app. //Regular expression for finding an email address.pointSize = 24. see FindGrep): var myDocument = app. app. //Clear the find/change preferences after the search. app.changeGrepPreferences.nothing.changeTextPreferences.findTextPreferences.changeTextPreferences = NothingEnum..]. app.findWhat = "(?i)[A-Z]*?@[A-Z]*?[. Using grep InDesign supports regular expression find/change through the findGrep and changeGrep methods.findChangeTextOptions.includeFootnotes = false. app.changeGrepPreferences = NothingEnum. NOTE: The findChangeGrepOptions object lacks two properties of the findChangeTextOptions object: wholeWord and caseSensitive.e.item(0).changeGrep(). as shown below: . app. app. //Search the document for the 24 point text and change it to 10 point text. app.documents. //Clear the find/change grep preferences. app. app.nothing. //Set the find options. This is because you can set these options using the regular expression string itself. //Set the find options.findChangeTextOptions. app.changeTextPreferences = NothingEnum.item(0).includeLockedLayersForFind = false.nothing. or use \b to match a word boundary.findChangeTextOptions..findGrepPreferences.findChangeTextOptions.findChangeGrepOptions.changeGrepPreferences = NothingEnum.changeText().findTextPreferences = NothingEnum.CHAPTER 6: Text and Type Finding and Changing Text 102 var myDocument = app. app. app.findGrepPreferences = NothingEnum.".includeLockedLayersForFind = false.includeFootnotes = false.pointSize = 24. Use (?i) to turn case sensitivity on and (?-i) to turn case sensitivity off. app. app.includeLockedStoriesForFind = false. app.includeLockedStoriesForFind = false. some form of tagging plain text with formatting instructions) into InDesign formatted text.findChangeGrepOptions.wholeWord = false.nothing. //Clear the find/change preferences after the search. //Clear the find/change preferences. app.nothing. Use \> to match the beginning of a word and \< to match the end of a word.

length. } myFoundTags = myRemoveDuplicates(myFoundTags). myCounter++){ myString = myFoundTags[myCounter]. we have a list of tags to search for. //the backslashes must be escaped).changeGrepPreferences = NothingEnum.documents. app.item(0).paragraphStyles. //Create the style if it does not already exist. app. //Reset the findGrepPreferences to ensure that previous settings //do not affect the search. function myReadPMTags(myStory){ var myName.length != 0){ var myFoundTags = new Array.changeText(). //Search to remove the tags. We can create a script that uses grep find in conjunction with text find/change operations to apply formatting to the text and remove the mark-up tags.nothing. //Extract the style name from the tag. myStyleName.documents.changeTextPreferences = NothingEnum. myStory. app.nothing.stories. myCounter < myFoundTags. var myFoundItems = myStory. as shown in the following script fragment (from the ReadPMTags tutorial script): var myDocument = app. myCounter++){ myFoundTags.changeTextPreferences = NothingEnum.nothing.changeTextPreferences. var myDocument = app. for(var myCounter = 0.contents). myReadPMTags(myStory). app. app.changeTo = "". app.item(myStyleName).substring(1. //Find the tag using findWhat. } } //Reset the findGrepPreferences. } //Apply the style to each instance of the tag. //Reset the changeTextPreferences.item.item(0). app. } catch (myError){ myStyle = myDocument.length-1). if(myFoundItems. //At this point.push(myFoundItems[myCounter].name. app.nothing.findWhat = myString. try{ myStyle = myDocument.changeText().add({name:myStyleName}).paragraphStyles. myStyleName = myString. myStyle. Here is the myReadPMTags function referred to in the above script.findGrepPreferences = NothingEnum. myStory. //Set the changeTo to an empty string.findTextPreferences. .findGrepPreferences = NothingEnum. //Find the tags (since this is a JavaScript string. myName = myStyle.appliedParagraphStyle = myStyle. <body_text>This is body text.CHAPTER 6: Text and Type Finding and Changing Text 103 <heading1>This is a heading.changeTextPreferences. var myStory = myDocument.findGrep().nothing. myString. for(myCounter = 0.length. myString. app. //Reset the find/change preferences again.findWhat = "(?i)^<\\s*\\w+\\s*>".findGrepPreferences. myCounter<myFoundItems.

glyphID = 374.appliedFont = app.appliedFont = app. app.changeGlyphPreferences = NothingEnum. see FindChangeGlyph): //Clear glyph search preferences.changeGlyphPreferences.length > 1){ for(var myCounter = 1. The following scripts fragment shows how to find and change a glyph in an example document (for the complete script.itemByName("Minion ProRegular").sort().push(myArray[myCounter]). app.documents. app. //Provide the glyph ID.nothing. much faster //than comparing every item to every other item! var myNewArray = new Array. app. see MakeTable): . myDocument. } } } return myNewArray. app.nothing.findGlyphPreferences. //Clear glyph search preferences.findGlyphPreferences. //The appliedFont of the changeGlyphPreferences object can be //any font available to the application. The following script fragment shows three different ways to create a table (for the complete script.fonts. myNewArray.glyphID = 85. app. app. Working with Tables Tables can be created from existing text using the convertTextToTable method. myArray = myArray.findGlyphPreferences = NothingEnum.findGlyphPreferences = NothingEnum.changeGlyph(false). } Using glyph search You can find and change individual characters in a specific font using the findGlyph and changeGlyph methods and the associated findGlyphPreferences and changeGlyphPreferences objects.push(myArray[0]). app.CHAPTER 6: Text and Type Working with Tables 104 } function myRemoveDuplicates(myArray){ //Semi-clever method of removing duplicate array items. not the glyph Unicode value.item(0).changeGlyphPreferences.nothing.fonts. //You must provide a font that is used in the document for the //appliedFont property of the findGlyphPreferences object. or an empty table can be created at any insertion point in a story.itemByName("Times New RomanBold").length.changeGlyphPreferences = NothingEnum.length -1]){ myNewArray. myCounter < myArray.nothing. var myDocument = app. if(myArray. myCounter ++){ if(myArray[myCounter] != myNewArray[myNewArray.

bodyRowCount = 4. see SplitTableCells. var myEndCharacter = myStory.stories. myTable.insertionPoints.texts. myEndCharacter).item(-2).documents.convertToTable(".rows.item(6). (For the complete script.rows. These are the default delimiter //parameters.item(0). var myStory = myDocument.item(0).columns. var myStartCharacter = myStory.merge(myTable.item(6). myTable.item(1)). var myText = myStory.cells.item(2).) . The following script fragment shows how to split table cells.item(0).) var myDocument = app.item(-2).merge(myTable.tables. so we don't need to provide them to the method.itemByRange(myStartCharacter. columns are separated by commas //and rows are separated by semicolons. myEndCharacter).insertionPoints. see MergeTableCells.".paragraphs.itemByRange(myStartCharacter.stories.item(1).item(0).add(). //Convert column 2 into 2 cells (rather than 4). //In the second through the fifth paragraphs.item(-2).columnCount = 4. var myEndCharacter = myStory.columnCount = 3.add().paragraphs.texts.merge(myTable. //The convertToTable method takes three parameters: //[ColumnSeparator as string] //[RowSeparator as string] //[NumberOfColumns as integer] (only used if the ColumnSeparator //and RowSeparator values are the same) //In the last paragraph in the story.characters.item(-1)). myTable.cells.cells.").cells.merge(myTable.bodyRowCount = 3. colums are separated by //tabs and rows are separated by returns. //Merge the last two cells in row 1.columns.tables.rows.item(-1)).item(0).columns.item(-2)). var myTable = myStory. //Merge all of the cells in the first column. var myStartCharacter = myStory. var myStory = myDocument.cells.item(-2). //You can also explicitly add a table--you don't have to convert text to a table.".cells.characters.item(1). myTable.columns. var myTable = myText. The following script fragment shows how to merge table cells.documents.item(0).paragraphs.item(0).item(4).item(0). myTable.CHAPTER 6: Text and Type Working with Tables 105 var myDocument = app.convertToTable().columns.merge(myTable. myTable. myTable.item(-1).item(1). myTable.item(-1). (For the complete script.item(-1).cells.item(1). so we provide those characters //to the method as parameters.item(-1)).item(0). //Merge the last two cells in row 3.cells.characters.item(0).characters.cells.cells. var myText = myStory.paragraphs.rows.item(2).item(0). var myTable = myText. var myTable = myStory.item(1). myTable.

everyItem().rows.horizontal).everyItem().swatches. myTable.fillTint = 40.item(0). myCellCounter ++){ myString = "Row: " + myRowCounter + " Cell: " + myCellCounter. myTable. myTable.bottomEdgeStrokeColor = myDocument.rows. myTable.item("DGC1_446b"). myTable.cells.footerRow.everyItem().swatches.everyItem(). } } The following script fragment shows how to create header and footer rows in a table (for the complete script.rightEdgeStrokeWeight = 0.headerRow.rows.item("DGC1_446a").item(0). myTable.swatches. myRowCounter < myTable.item(0). //Convert the first row to a header row.vertical). //Convert the last row to a footer row.leftEdgeStrokeWeight = 0.split(HorizontalOrVertical.columnCount = 1.item(0).item("DGC1_446b").item(0).insertionPoints.item(0)) var myWidth = myArray[3]-myArray[1]. myTable.columns.item("None").item(0).rowType = RowTypes.rowType = RowTypes.rows.item(1). myTable. myTable.length.pages. myTable.fillColor = myDocument.rows.everyItem().rows.vertical). myTable.bodyRowCount = 1.rows.item(myRowCounter).fillTint = 20.rows.leftEdgeStrokeColor = myDocument. for(myRowCounter = 0.cells. myTable. //Convert the first row to a header row. myTable. myDocument.item("DGC1_446b").bottomEdgeStrokeWeight = 1.item("None"). myRowCounter ++){ myRow = myTable.item(0).documents.split(HorizontalOrVertical.rows.cells.cells.rows.cells.item("DGC1_446a"). myTable.split(HorizontalOrVertical. //Use a reference to a swatch.stories.cells.tables.rows. make certain //that you also set the stroke weight. myTable.item(0). . myTable. var myTable = myDocument.item("DGC1_446a").item(-1).item(2).topEdgeStrokeColor = myDocument.item(3).add().cells. myTable. myTable.everyItem(). for(myCellCounter = 0.fillColor = myDocument.cells.rows.item(0).CHAPTER 6: Text and Type Working with Tables 106 var myStory = myDocument.horizontal).split(HorizontalOrVertical. myTable.swatches.swatches. myRow. see TableFormatting): var myDocument = app.documents. see HeaderAndFooterRows): var myDocument = app.rows.cells. myTable.fillColor = myDocument.item(0).fillTint = 40.stories. myTable.swatches.everyItem().topEdgeStrokeWeight = 1. rather than to a color. var myTable = myStory.tables.stories.item(-1).tables.swatches.width = myWidth.item(0).rows.fillColor = myDocument.headerRow.length. myTable. myCellCounter < myRow.cells. myTable.rowType = RowTypes.item(-1). myTable.fillTint = 40.cells.item(0). //When you set a cell stroke to a swatch.item(0). myTable. The following script fragment shows how to apply formatting to a table (for the complete script.item(1). myTable.rightEdgeStrokeColor = myDocument.cells.item(myCellCounter).swatches.item(0).vertical).item(0). var myArray = myGetBounds(myDocument.cells.item(2). var myTable = myDocument.everyItem().split(HorizontalOrVertical. myTable. //Use everyItem to set the formatting of multiple cells at once.item(3).contents = myString.columns.item(-1).

CHAPTER 6: Text and Type Working with Tables 107 The following script fragment shows how to add alternating row formatting to a table (for the complete script. case "Table": alert("A table is selected.").").item("DGC1_446a"). case "Image": case "PDF": case "EPS": if(app. The following script fragment shows how to process the selection when text or table cells are selected.selection.parent. In this example.parent. the script displays an alert for each selection condition. case "Rectangle": case "Oval": case "Polygon": case "GraphicLine": if(app.name == "Cell"){ alert("The selection is inside a table cell.endRowFillTint = 50. (For the complete script. } } } .alternatingFills = AlternatingFillsTypes.documents.name){ //When a row. break." apply alternating fills to the table.selection[0].name == "Cell"){ alert("The selection is inside a table cell. myTable.constructor.swatches. } break.item("DGC1_446b").constructor. //the type returned is "Cell" case "Cell": alert("A cell is selected.endRowFillColor = myDocument.name == "Cell"){ alert("The selection is inside a table cell. a column.selection[0].").selection[0].startRowFillColor = myDocument. see AlternatingRows): //Given a table "myTable.constructor. default: alert("The selection is not inside a table."). break.startRowFillTint = 60. case "InsertionPoint": case "Character": case "Word": case "TextStyleRange": case "Line": case "Paragraph": case "TextColumn": case "Text": if(app. myTable. see TableSelection.parent.parent. break.selection[0]. myTable.").constructor. } break.").) if(app. } break. myTable. but a real production script would then do something with the selected item(s).length != 0){ if(app.parent. myTable. or a range of cells is selected.swatches.parent.alternatingRows.length != 0){ switch(app.

add({contents:"This is path text.pages.item(-1). app. "paragraph"]).footnotes. see Footnotes): var myDocument = app. //Update the word pair list. myAutoCorrectTable.textFrames.autoCorrectPreferences.item(0).autoCorrectWordPairList = myWordPairList.insertionPoints.textPaths. append //the footnote text. var myWordPairList = myAutoCorrectTable.rectangles. var myPage = myDocument. var myAutoCorrectTable = app. Footnotes The following script fragment shows how to add footnotes to a story (for the complete script.item(0). myFootnote. //To clear all autocorrect word pairs in the current dictionary: //myAutoCorrectTable. //To safely add a word pair to the auto correct table. it contains text--the footnote marker //and the separator text (if any). var myFootnote = myWord. polygon. var myTextPath = myRectangle. myCounter < 4.add(). } . myWordPairList.length)). graphic line. var myRectangle = myPage. //Note: when you create a footnote.".. just as you would for a text frame (see “Working with Text Frames” on page 86). as shown below.CHAPTER 6: Text and Type Path Text 108 Path Text You can add path text to any rectangle. Autocorrect The autocorrect feature can correct text as you type.item(0). you will delete the marker. var myPage = myDocument.parentStory. for(myCounter = 0.item("English: USA"). To link text paths to another text path or text frame.autoCorrectWordPairList.pages.push(["paragarph".item(-1).insertionPoints. get the current //word pair list. and then //set the autocorrect word pair list to the array.documents.autoCorrectTables. The following script fragment shows how to add path text to a page item (for the complete script. Instead.autoCorrectWordPairList = [[]]. //Add a word pair to the autocorrect list. var myTextFrame = myPage. app. then add the new word pair to that array.contents = "This is a footnote.item(0). see PathText): //Given a document "myDocument" with a rectangle on page 1. use the nextTextFrame and previousTextFrame properties.words.autoCorrect = true. Each AutoCorrectTable is linked //to a specific language. The following script shows how to use it (for the complete script.autoCorrectPreferences. see Autocorrect): //The autocorrect preferences object turns the //autocorrect feature on or off. or text frame."}).parentStory. including the myGetRandom function. //Add a new word pair to the array.autoCorrectCapitalizationErrors = true. myCounter ++){ myWord = myTextFrame. oval. //Add four footnotes at random locations in the story. myTextFrame.words.item(0)..item(myGetRandom(0. If you try to set the text of the footnote //by setting the footnote contents.

var myPage = myDocument. spanSplitColumnCount = 2.paragraphs[0]) { spanColumnType = SpanColumnTypeOptions.pages. highlightSubstitutedGlyphs = true. highlightSubstitutedFonts = true.paragraphs[mySpanIndex]) { spanColumnType = SpanColumnTypeOptions. highlightHjViolations = true.splitColumns.paragraphs.item(0). //Split Column with(myStory. showInvisibles = true.textFrames.CHAPTER 6: Text and Type Span Columns 109 Span Columns A paragraph layout can span multiple columns or split into subcolumns with the Span Columns attribute or Split Column attribute applied.item(0).spanColumns. see SpanColumns): var myDocument = app.documents.001 to 200 points. } Setting Text Preferences The following script shows how to set general text preferences (for the complete script.all. linkTextFilesWhenImporting = false. spanSplitColumnCount = SpanColumnCountOptions. highlightCustomSpacing = false. var myTextFrame = myPage. with(myStory.length / 2). //kerning key increment value is 1/1000 of an em. } //Span Columns var mySpanIndex = Math. scalingAdjustsText = false.textPreferences" with(app. myTextFrame.activeDocument. kerningKeyIncrement = 10.textPreferences){ abutTextToTextWrap = true. replace "app. splitColumnOutsideGutter = 0. //baseline shift key increment can range from . see TextPreferences): //The following sets the text preferences for the application.parentStory. justifyTextWraps = true. //leading key increment value can range from . baselineShiftKeyIncrement = 1. to set the //text preferences for the front-most document. splitColumnInsideGutter = 1. subscriptPosition = 30. smallCap = 60.textFramePreferences. .floor(myStory. The following script fragment shows how to set the Span Columns and Split Column style for a paragraph (for the complete script.textColumnCount = 3. leadingKeyIncrement= 1. highlightKeeps = true.item(0).textPreferences" with //"app. var myStory = myTextFrame.001 to 200 points.

} . } //Text editing preferences are application-wide. useOpticalSize = false. typographersQuotes = false.textEditingPreferences){ allowDragAndDropTextInStory = true.CHAPTER 6: Text and Type Setting Text Preferences 110 subscriptSize = 60. superscriptSize = 60. tripleClickSelectsLine = false. dragAndDropTextInLayout = true. smartCutAndPaste = true. superscriptPosition = 30. useParagraphLeading = false. with(app. zOrderTextWrap = false.

NOTE: InDesign scripts written in JavaScript also can include user interfaces created using the Adobe ScriptUI component. The sample scripts in this chapter are presented in order of complexity. for more information. This chapter shows how to work with InDesign dialog scripting. The dialog box can contain several different types of elements (known collectively as “widgets”). dialog dialog column static text border panel checkbox control radiobutton group radiobutton control measurement editbox dropdown 111 . use the dialog object. but you probably will need to create more complex dialogs for your scripts. If you want your script to collect and act on information entered by you or any other user of your script. Dialog Overview An InDesign dialog box is an object like any other InDesign scripting object. see Adobe CS5 JavaScript Tools Guide. InDesign scripting can add dialogs and populate them with common user-interface controls. text-entry fields. We assume that you have already read Adobe InDesign CS5 Scripting Tutorial and know how to create and run a script. The elements of the figure are described in the table following the figure. as shown in the following figure. This chapter includes some ScriptUI scripting tutorials.7 User Interfaces JavaScript can create dialogs for simple yes/no questions and text entry. like pop-up lists. and numeric-entry fields. starting with very simple scripts and building toward more complex operations.

Your First InDesign Dialog The process of creating an InDesign dialog is very simple: add a dialog. and add controls to the dialog column. see SimpleDialog): var myDialog = app. but it also means the dialog boxes take up memory and should be disposed of when they are not in use. measurement editbox. for example. To use a dialog box in your script. display one message. add a dialog column to the dialog."}). Inside dialogColumns. angle editbox Drop-down control Combo-box control Check-box control Radio-button control The dialog object itself does not directly contain the controls.dialogs. } //Show the dialog box. if(myResult == true){ alert("You clicked the OK button. The following script demonstrates the process (for the complete script.dialogColumns. percent editbox. This means you can keep a dialog box in memory and have data stored in its properties used by multiple scripts. The dropdown control has a property (stringList) for setting the list of options that appears on the control’s menu. if necessary. //If the user clicked OK. you should destroy a dialog-box object before your script finishes executing."). . myDialog.CHAPTER 7: User Interfaces Your First InDesign Dialog 112 Dialog box element Text-edit fields Numeric-entry fields Pop-up menus Control that combines a text-edit field with a pop-up menu Check box Radio buttons InDesign name Text editbox control Real editbox. each part of a dialog box has its own properties. and then gather values from the dialog-box controls to use in your script. dialogColumns give you a way to control the positioning of controls within a dialog box. } //Remove the dialog box from memory.destroy(). A checkboxControl. //Add a dialog column. you can further subdivide the dialog box into other dialogColumns or borderPanels (both of which can. //if they clicked Cancel. populate it with various controls.add()){ staticTexts. contain more dialogColumns and borderPanels). var myResult = myDialog.add({name:"Simple Dialog"}). integer editbox. create the dialog object.show(). with(myDialog. In general.add({staticLabel:"This is a very simple dialog box. display the dialog box."). has a property for its text (staticLabel) and another property for its state (checkedState). Dialog boxes remain in InDesign’s memory until they are destroyed. that is the purpose of the dialogColumn object. } else{ alert("You clicked the Cancel button. display a different message. Like any other InDesign scripting object.

show().destroy(). var myTextFrame = pages.points}).texts.add({editContents:"Hello World!".pointSize = myPointSize.contents=myString. myDialog. var myBounds = myGetBounds(myDocument. //Create a number (real) entry field.editContents.documents.add({editValue:72.dialogs. //Enter the text from the dialog box in the text frame.add() with(myDocument){ //Create a text frame. //Remove the dialog box from memory.add()){ //Create a text edit field. myMakeDocument(myString.CHAPTER 7: User Interfaces Adding a User Interface to “Hello World” 113 Adding a User Interface to “Hello World” In this example.add({name:"Simple User Interface Example Script". if(myResult == true){ //Get the values from the dialog box controls. var myResult = myDialog. } Here is the myMakeDocument function referred to in the above fragment: function myMakeDocument(myString. editUnits:MeasurementUnits. var myPointSize = myPointSizeField.item(0)).add(). myPointSize).geometricBounds=myBounds. } } Creating a More Complex User Interface In the next example. } } //Display the dialog box. var myString = myTextEditField. myTextFrame. with(myDialog){ //Add a dialog column.editValue.destroy().pages. The example creates a dialog box that resembles the following: . //Resize the text frame to the "live" area of the page //(using the function "myGetBounds").canCancel:true}). myTextFrame. myPointSize){ //Create a new document. //Set the size of the text to the size you entered in the dialog box. } else{ myDialog.item(0). var myPointSizeField = measurementEditboxes. we add more controls and different types of controls to the sample dialog box. we add a simple user interface to the Hello World tutorial script presented in Adobe InDesign CS5 Scripting Tutorial. The options in the dialog box provide a way for you to specify the sample text and change the point size of the text: var myDialog = app. var myDocument = app. myDocument. myTextFrame. with(dialogColumns.item(0). var myTextEditField = textEditboxes. minWidth:180}).textFrames.

var myRadioButtonGroup = radiobuttonGroups. with(dialogColumns.add({staticLabel:"Point Size:"}). var myDialog = app.add()){ with(dialogColumns.add()){ //The following line shows how to set multiple properties //as you create an object.add()){ //The following line shows how to set a property as you create an object.add({name:"User Interface Example Script". "Bottom"].CHAPTER 7: User Interfaces Creating a More Complex User Interface 114 For the complete script.add(). } } //Create another border panel. minWidth:180}). } } //Create another border panel. with(borderPanels. } } //Create another border panel. staticTexts. with(borderPanels. with(borderPanels. see ComplexUI.add({staticLabel:"Paragraph Alignment:"}). } with(dialogColumns. with(borderPanels. canCancel:true}). Note that this field uses editValue //rather than editText (as a textEditBox would). "Center". } with(dialogColumns. var myVerticalJustificationMenu = dropdowns.add({staticLabel:"Vertical Justification:"}).add()){ //Create a border panel.add ({stringList:["Top". with(myRadioButtonGroup){ var myLeftRadioButton = radiobuttonControls. var myPointSizeField = measurementEditboxes.add .add ({editContents:"Hello World!".add()){ with(dialogColumns. } with(dialogColumns.add()){ //Create a number entry field. with(myDialog){ //Add a dialog column.add()){ staticTexts.add()){ staticTexts.add({editValue:72}).add()){ //Create a pop-up menu ("dropdown") control.add()){ staticTexts.dialogs. selectedIndex:0}).add({staticLabel:"Message:"}).add()){ with(dialogColumns. var myTextEditField = textEditboxes.

} else if(myRadioButtonGroup.bottomAlign.selectedButton == 0){ myParagraphAlignment = Justification. } else if(myVerticalJustificationMenu.show() == true){ var myParagraphAlignment. } else{ myVerticalJustification = VerticalJustification.selectedIndex == 0){ myVerticalJustification = VerticalJustification.add({staticLabel:"Right"}).rightAlign. myMakeDocument(myString. myString. checkedState:true}). myParagraphAlignment.selectedIndex == 1){ myVerticalJustification = VerticalJustification. var myCenterRadioButton = radiobuttonControls. } } } } //Display the dialog box. } //Get the paragraph alignment setting from the radiobutton group. //Get the vertical justification setting from the pop-up menu. myPointSize. if(myVerticalJustificationMenu.add ({staticLabel:"Center"}).centerAlign.leftAlign. } else{ myDialog. var myRightRadioButton = radiobuttonControls. //If the user didn't click the Cancel button. if(myDialog.destroy() } Here is the myMakeDocument function referred to in the above fragment: .centerAlign.CHAPTER 7: User Interfaces Creating a More Complex User Interface 115 ({staticLabel:"Left".destroy(). } else{ myParagraphAlignment = Justification. //then get the values back from the dialog box. myPointSize. if(myRadioButtonGroup. } myDialog.selectedButton == 1){ myParagraphAlignment = Justification.editValue. myVerticalJustification). myVerticalJustification. //Get the example text from the text edit field.editContents //Get the point size from the point size field.topAlign. myString = myTextEditField. myPointSize = myPointSizeField.

myVerticalJustification){ //Create a new document. Creating a progress bar with ScriptUI The following sample script shows how to create a progress bar using JavaScript and ScriptUI. then use the progress bar from another script (for the complete script.textFrames. var myPage = pages[0]. var myMaximumValue = 300. var myTextFrame = pages. with(myProgressPanel){ myProgressPanel. [12. InDesign scripts can execute scripts written in other scripting languages using the method.points. myProgressBarWidth){ myProgressPanel = new Window('window'. textFramePreferences.pointSize = myPointSize. with(myDocument){ viewPreferences. myProgressBarWidth). var myDocument = app. that user-interface elements written using Script UI are not accessible to users. } } . myPointSize. myProgressBarWidth. texts.documents. and interactive dialog boxes that are far more complex than InDesign’s built-in dialog object. progress bars. viewPreferences. myParagraphAlignment. with(myPage){ //Create a text frame. //Set the vertical justification of the text frame.myProgressBar = add('progressbar'. see ProgressBar): #targetengine "session" //Because these terms are defined in the "session" engine.CHAPTER 7: User Interfaces Working with ScriptUI 116 function myMakeDocument(myString.item(0). 24].item(0). 'Progress'). var myProgressBarWidth = 300. 12.verticalJustification = myVerticalJustification. } } } } Working with ScriptUI JavaScripts can make create and define user-interface elements using an Adobe scripting component named ScriptUI.verticalMeasurementUnits = MeasurementUnits. geometricBounds = myGetBounds(myDocument. //Set the contents of the frame to the string you //entered in the dialog box.points. var myIncrement = myMaximumValue/myProgressBarWidth. with(myTextFrame){ //Set the geometric bounds of the frame using the "myGetBounds" function. function myCreateProgressPanel(myMaximumValue. This does not mean. 0. however. myMaximumValue).horizontalMeasurementUnits = MeasurementUnits. texts.add(). //Set the alignment of the paragraph.justification = myParagraphAlignment.item(0).add(). contents = myString. //they will be available to any other JavaScript running //in that instance of the engine. //Set the point size of the text. myPage). ScriptUI gives scripters a way to create floating palettes. myCreateProgressPanel(myMaximumValue.

Add myString = "#targetengine ""session""" & vbCr myString = myString & "myProgressPanel. myInDesign.show(). see CallProgressBar): Rem Create a document and add pages to it-Rem if you do not do this." & vbcr myString = myString & "myProgressPanel. idScriptLanguage.DoScript myString. myString = "#targetengine ""session""" & vbCr myString = myString & "myCreateProgressPanel(100.value = 0. 400).Pages.Close idSaveOptions.idJavascript If(myCounter = 100) Then myString = "#targetengine ""session""" & vbCr myString = myString & "myProgressPanel.idNo End If Next . idScriptLanguage.idJavascript myDocument.DoScript myString.Add Rem Note that the JavaScripts must use the "session" Rem engine for this to work.value = " myString = myString & cstr(myCounter) & "/myIncrement." & vbcr myInDesign. the progress bar Rem will go by too quickly.idJavascript For myCounter = 1 to 100 Rem Add a page to the document.Documents.Item(1)." & vbcr myString = myString & "myProgressPanel.Documents.myProgressBar.hide().DoScript myString.CHAPTER 7: User Interfaces Working with ScriptUI 117 The following script fragment shows how to call the progress bar created in the above script using a separate JavaScript (for the complete script. idScriptLanguage." & vbcr myInDesign.myProgressBar." & vbcr myInDesign. Set myDocument = myInDesign.

and run a script. 118 . The first object is the event. About event properties and event propagation When an action—whether initiated by a user or by a script—triggers an event. or propagate.” The InDesign event scripting model is similar to the Worldwide Web Consortium (W3C) recommendation for Document Object Model Events. There are two types of event propagation: None — Only the eventListeners registered to the event target are triggered by the event. printing. “Menus. When the specified event reaches the object. such as opening a file. the eventListener executes the script function defined in its handler function (which can be either a script function or a reference to a script file on disk). You can view the available events using the Object Model Viewer in the ExtendScript Toolkit. starting with very simple scripts and building toward more complex operations. select the Event class.org. Scripts that use events are the same as other scripts—the only difference is that they run automatically when the corresponding event occurs. The event then proceeds upward through the scripting object model. Scripts can be attached to events using the eventListener scripting object. Bubbling — The event starts propagation at its target and triggers any qualifying eventListeners registered to the target.8 Events InDesign scripting can respond to common application and document events. install. We assume that you have already read Adobe InDesign CS5 Scripting Tutorial and know how to create. then click Class in the Types list to display a list of available event types in the Properties and Methods list. In InDesign scripting. For a discussion of events related to menus. and importing text and graphic files from disk. An event can be handled by more than one object as it propagates. the eventListener is triggered by the event. When an event reaches an object that has an eventListener registered for that event. For more information. In the ExtendScript Toolkit. the event object responds to an event that occurs in the application. see Chapter 9. The beforeDisplay event is an example of an event that does not propagate. This chapter shows how to work with InDesign event scripting. you register an eventListener with an object capable of receiving the event. rather than being run by the user (from the Scripts palette). the event can spread. Understanding the Event Scripting Model The InDesign event scripting model consists of a series of objects that correspond to the events that occur as you work with the application. creating a new file. through the scripting objects capable of responding to the event. To respond to an event. The sample scripts in this chapter are presented in order of complexity. which corresponds to one of a limited series of actions in the InDesign user interface (or corresponding actions triggered by scripts).w3c. see http://www.

the event may still be processed by other eventListeners that might be monitoring the event (depending on the propagation of the event). see AddEventListener).addEventListener("afterNew". If true. Cancelable CurrentTarget DefaultPrevented EventPhase EventType PropagationStopped Target TimeStamp Working with Event Listeners When you create an eventListener. . For example. The object from which the event originates. To do this. the afterOpen event can be observed by eventListeners associated with both the application and the document. as a string (for example. When an eventListener responds to an event. If true. the event propagates to scripting objects above the object initiating the event. the application. false). The current stage of the event propagation process. If true. var myEventListener = app. The following script fragment shows how to add an eventListener for a specific event (for the complete script. myDisplayEventType). } To remove the eventListener created by the preceding script. you specify the event type and the event handler (as a function or file reference). the default behavior of the event on the current target was prevented. To stop event propagation. The type of the event. run the following script (from the RemoveEventListener tutorial script): app. use the stopPropagation method . The preceding script fragment refers to the following function: function myDisplayEventType(myEvent){ alert("This event is the " + myEvent.removeEventListener("afterNew".CHAPTER 8: Events Working with Event Listeners 119 triggering any qualifying eventListeners registered to objects above the target in the scripting object model hierarchy. thereby canceling the action. use the PreventDefault method . "beforeNew"). the default behavior of the event on its target can be canceled.").eventType + " event. See target in this table. of a beforeNew event. Property Bubbles Description If true. The current scripting object processing the event. The time and date when the event occurred. myDisplayEventType. the target of a beforeImport event is a document. For example. See target in this table. The following table provides more detail on the properties of an event and the ways in which they relate to event propagation through the scripting object model. the event has stopped propagating beyond the current target (see target in this table).

"beforeRevert".CHAPTER 8: Events Working with Event Listeners 120 eventListeners do not persist beyond the current InDesign session. NOTE: If you are having trouble with a script that defines an eventListener.scriptPreferences. "afterNew". } When you run the preceding script and place a file. "afterSaveAs". "afterSaveACopy". To make an eventListener available in every InDesign session.eventListeners. then the name of the application. For the complete script. "afterRevert". "afterClose".) When you add an eventListener script to a document. } } function myEventInfo(myEvent){ var myString = "Handling Event: " +myEvent. "beforePrint". The following sample script demonstrates an event triggering eventListeners registered to different objects (for the full script. see "Installing Scripts" in Adobe InDesign CS5 Scripting Tutorial. main() function main(){ app. myEventInfo). in sequence. InDesign displays alerts showing.target + " " +myEvent.name.name.currentTarget.target.length. myCounter ++){ app.add("beforeImport". "beforeSave". "afterExport". "afterPrint".eventType. If the script is run using #targetengine "main" (the default). for (var myCounter = 0. eventListeners that use handler functions defined inside the script (rather than in an external file) must use #targetengine "session". it is not saved with the document or exported to IDML. function main(){ var myApplicationEventListener = app.item(0). you can either run a script that removes the eventListener or quit and restart InDesign. alert(myString).addEventListener(myEventNames[myCounter]. the function is not available when the event occurs. myCounter < myEventNames. myEventInfo).version = 5. "beforeSaveACopy". } function myEventInfo(myEvent){ var myString = "Current Target: " + myEvent. run the RemoveMultipleEventListeners script. An event can trigger multiple eventListeners as it propagates through the scripting object model. and the script generates an error. myString += "\r\rTarget: " + myEvent. "afterSave". var myEventNames = [ "beforeQuit". "afterImport" ] . "afterOpen". see MultipleEventListeners): #targetengine "session" main().eventListeners. "beforeSaveAs". "beforeClose".add ("beforeImport". "afterQuit". To remove the event listeners added by the preceding script. add the script to the startup scripts folder. "beforeNew".documents. "beforeImport". see EventListenersOn. the name of the document. "beforeExport". var myDocumentEventListener = app. myEventInfo).0. . "beforeOpen". The following sample script creates an eventListener for each document event and displays information about the event in a simple dialog box. (For more on installing scripts.

alert(myString).timeStamp.parent. #targetengine "session" //Creates an event listener that will run after a new document is created.bubbles. myString += "\rCanceled: " +myEvent. } return myPhaseName.viewPreferences. The following tutorial script shows how to add this kind of information to a text frame in the slug area of the first master spread in the document (for the complete script. myString += "\r\rPhase: " + myGetPhaseName(myEvent.eventPhase ). break. see EventListenersOff.everyItem(). myAddXMPData(myDocument).eventListeners.bubblingPhase: myPhaseName = "Bubbling". the date the document was created. myDocument. case EventPhases. break.done: myPhaseName = "Done". myDocument.propagationStopped. This script also adds document metadata (also known as file info or XMP information). myString += "\r\rTime: " +myEvent. For the complete script. case EventPhases. function myCreateSlug(myDocument){ .pageOrigin. copyright information. myCreateSlug(myDocument).viewPreferences.cancelable. see AfterNew). main(). } } The following sample script shows how to turn off all eventListeners on the application object.currentTarget. case EventPhases. myAfterNewHandler). break. #targetengine "session" app.rulerOrigin = RulerOrigin.horizontalMeasurementUnits = MeasurementUnits. } function myAfterNewHandler(myEvent){ var myDocument = myEvent.add("afterNew". and other job-tracking information.viewPreferences. function myGetPhaseName(myPhase){ switch(myPhase){ case EventPhases.CHAPTER 8: Events Sample afterNew Event Listener 121 myString += "\rCurrent: " +myEvent. such as the user name.points.currentTarget + " " + myEvent. myDocument. myString += "\rStopped: " +myEvent. myString += "\r\rCancelable: " +myEvent.verticalMeasurementUnits = MeasurementUnits.atTarget: myPhaseName = "At Target".notDispatching: myPhaseName = "Not Dispatching".remove(). Sample afterNew Event Listener The afterNew event provides a convenient place to add information to the document.points. function main(){ var myEventListener = app.name.eventListeners. myString += "\rBubbles: " + myEvent. break.defaultPrevented.

myPage. } } Sample beforePrint Event Listener The beforePrint event provides a perfect place to execute a script that performs various preflight checks on a document.right.timeStamp + "\rby: " + app.userName}). } } function myGetSlugBounds(myDocument. we have to use a special case for //left hand pages. mySlugOffset. myCounter < myDocument.metadataPreferences){ author = "Adobe Systems". myY2.documentPreferences.length. var myY2 = myY1 + mySlugHeight. description = "This is a sample document with XMP metadata.pages. myX2]. mySlugOffset. myPage. myX1. var myPageHeight = myDocument. } for(var myCounter = 0. myPage.left. } else{ var myX1 = myPage. for(var myMasterPageCounter = 0. contents:"Created: " + myEvent.myPage. slugRightOrOutsideOffset = 0. var mySlugOffset = 24. slugTopOffset = 0.masterSpreads. var mySlugHeight = 72. The following script shows how to add an event listener that checks a document for certain attributes before printing (for the complete script. mySlugHeight){ var myPageWidth = myDocument. //mySlugHeight is the height of the slug text frame.add( {geometricBounds:mySlugBounds. var myX2 = myPageWidth .marginPreferences. myMasterPageCounter < myMasterSpread. if(myPage. var mySlugBounds = myGetSlugBounds(myDocument. return [myY1.side == PageSideOptions.". myMasterPageCounter ++){ var myPage = myMasterSpread.left.pageHeight //Because "right" and "left" margins become "inside" and "outside" //for pages in a facing pages view.marginPreferences. } } } function myAddXMPData(myDocument){ with(myDocument.pages.length. with(myDocument.CHAPTER 8: Events Sample beforePrint Event Listener 122 //mySlugOffset is the distance from the bottom of the page to //the top of the slug.documentPreferences. myCounter++){ var myMasterSpread = myDocument.leftHand){ var myX2 = myPageWidth . slugBottomOffset = mySlugOffset + mySlugHeight.pageWidth. } var myY1 = myPageHeight + mySlugOffset. var myX1 = myPage.marginPreferences. see BeforePrint): .marginPreferences.textFrames.item(myCounter).item(myMasterPageCounter).right. slugInsideOrLeftOffset = 0. var mySlugFrame = myPage.documentPreferences){ documentSlugUniformSize = false. mySlugHeight).masterSpreads.

} function myCheckGraphics(myDocument){ var myGraphicsCheck = true. myEvent.itemLink. if((myFontCheck == false)||(myGraphicsCheck == false)){ myPreflightCheck = false.fonts. } } Sample Selection Event Listeners InDesign can respond to events related to selection. myCounter++){ var myGraphic = myDocument. } else{alert("Document passed preflight check. InDesign generates the afterSelectionChanged event.add("beforePrint".allGraphics[myCounter].status != LinkStatus. var myDocument = myEvent. myCounter < myDocument. main()."). for(var myCounter = 0.CHAPTER 8: Events Sample Selection Event Listeners 123 #targetengine "session" //Adds an event listener that performs a preflight check on a document //before printing.fonts.length.length. alert("Document did not pass preflight check. } } return myGraphicsCheck. } return myPreflightCheck. } function myBeforePrintHandler(myEvent){ //The parent of the event is the document. alert("Fonts: " + myFontCheck + "\r" + "Links:" + myGraphicsCheck).eventListeners. myCounter < myDocument. These two events are useful when you want to create a script that responds to user actions.").normal){ myGraphicsCheck = false. var myGraphicsCheck = myCheckGraphics(myDocument).item(myCounter). for(var myCounter = 0. .parent.allGraphics. } function myCheckFonts(myDocument){ var myFontCheck = true.preventDefault(). function main(){ var myEventListener = app. if(myPreflight(myDocument) == false){ myEvent. var myFontCheck = myCheckFonts(myDocument). } } return myFontCheck.stopPropagation(). InDesign generates the afterSelectionAttributeChanged event. the script cancels //the print job. myBeforePrintHandler). When you select or deselect objects in an InDesign document. When you change an attribute (the formatting or position) of the selected object or objects. Ready to print. if(myGraphic.status != FontStatus.installed){ myFontCheck = false. myCounter ++){ if(myDocument. If the preflight check fails.} function myPreflight(myDocument){ var myPreflightCheck = true.

The event handler referred to in the preceding script fragment looks like this: function myCheckForRegistration(myEvent){ var myRegistrationSwatchUsed = false. For the complete script.selection.documents.length.name + "\r" } alert(myString). if(app. myDocument. The onIdle event provides a way to run scripting-based idle tasks. It . } } To remove the event listener added by the preceding script.swatches. myCounter++){ myString = myString + mySelection[myCounter].item(0). It is easy to run idle tasks by scripting. see AfterSelectionAttributeChanged. var myDocument = app. the script asks whether the change was intentional.documents.CHAPTER 8: Events Sample onIdle Event Listener 124 The following script fragment shows how to get and display the type of an object when the selection changes.item(0). (Accidental application of the Registration swatch can cause problems at your commercial printer. In this example. see AfterSelectionChanged.item(0). var myString = "Selection Contents:\r".documents. Sample onIdle Event Listener InDesign’s idle tasks execute when there are no events in the event queue for the application to process.documents.strokeColor == app. run the RemoveAfterSelectionAttributeChanged script.) If the Registration swatch has been applied. the event handler checks the selection to see whether the Registration swatch has been applied.item("Registration")){ myRegistrationSwatchUsed = true.documents. Did you really intend to apply this swatch?"). app.addEvenListener("afterSelectionAttributeChanged". myCounter++){ if((app.item(0).documents. The event handler referred to in the preceding script fragment looks like this: function myDisplaySelectionType(myEvent){ if(app. for(var myCounter = 0.addEventListener("afterSelectionChanged". The following script fragment shows how to respond to a change in the attributes of a selection.add().swatches.documents.selection[myCounter].selection.documents.selection[myCounter]. } } } To remove the event listener added by the preceding script. myCounter < mySelection. myCounter < app.item("Registration"))|| (app. run the RemoveAfterSelectionChanged script.constructor. myDisplaySelectionType).selection.length != 0){ for(var myCounter = 0.item(0). } } } if(myRegistrationSwatchUsed == true){ alert("The Registration swatch is applied to some of the\robjects in the selection. For the complete script.length != 0){ var mySelection = app.length. myCheckForRegistration).fillColor == app.length != 0){ if(app.item(0).selection.

add(). "288pt".length == 0) { var myDoc = app.item(0). sleep:10000}). if (myTextFrames. Setting the sleep time to zero deletes the task (though it does not remove the event listener). The sleep property of the idle task is the amount of time that elapses before InDesign calls the task again.").pages. "72pt".parent.addEventListener(IdleEvent.name + ". The following script shows how to add an eventListener and show a message box from the idle task (for the complete script. and its event object is IdleEvent. } var myTextFrames = app.name + " in idle task.sleep = 0. "288pt"]."). alert("Nothing to do. myTextFrame. myIdleEvent. added event listener on " + onIdleEventListener.idleTasks. though this value will vary depending on what tasks the script performs. var onIdleEventListener = myIdleTask.documents.textFrames. false). } //Delete idle task by setting its sleep time to zero. } function onIdleEventHandler(myIdleEvent) { if (app.CHAPTER 8: Events Sample onIdle Event Listener 125 can be used to automatically execute a script when InDesign/InCopy is idle. It should be obvious that you need to set the sleep time to a value high enough that it does not interfere with your work.eventType). return. onIdleEventHandler. see Reminder): #targetengine "session" main().activeDocument.documents. alert("Created a text frame in idle task. alert("Created document " + myDoc.add(). run the following script (for the complete script.contents = "Text frame created in idle task".length == 0) { var myTextFrame = myTextFrames. return. Delete idle task. myTextFrame. Its event target is IdleTask. see RemoveIdleTask): .geometricBounds = ["72pt". alert("Created idle task " + myIdleTask. } To remove the idle task created by preceding script.ON_IDLE. This is the most convenient way to stop an idle task."). function main() { var myIdleTask = app.add({name:"my_idle_task".

} else { for (var i = length-1.remove(). i >=0.length == 0) { alert("There is no idle task. i--) { app.CHAPTER 8: Events Sample onIdle Event Listener 126 #targetengine "session" main().idleTasks.idleTasks.itemByName(myIdleTaskName).")."). run the following script (for the complete script. } } To list existing idle tasks.idleTasks.idleTasks. run the following script (for the complete script. function main() { var length = app. } else { alert("There is no idle task " + myIdleTaskName). see RemoveAllIdleTasks): #targetengine "session" main(). if (myIdleTask != null) { myIdleTask. } } } To remove all idle tasks.remove().length.").item(i). var myIdleTask = app. see ListIdleTasks): . } else { var myIdleTaskName = "my_idle_task". } alert(length + " idle task(s) removed. if (length == 0) { alert("There is no idle task. function main() { if (app.

idleTasks. for (var i = 0.idleTasks.CHAPTER 8: Events Sample onIdle Event Listener 127 #targetengine "session" main().length. } alert(str). i++) { var myIdleTask = app.name + "\n". } } . if (length == 0) { alert("There is no idle task.item(i). } else { var str = "". i < length.id + ": " + myIdleTask."). function main() { var length = app. str += "idle task " + myIdleTask.

starting with very simple scripts and building toward more complex operations. This chapter shows how to work with InDesign menu scripting. The sample scripts in this chapter are presented in order of complexity. InDesign scripters can create their own. and run a script. A menuAction or scriptMenuAction can be connected to zero. or more menuItems. In addition to the menuActions defined by the user interface. The properties of the menuAction define what happens when the menu item is chosen. This does not include submenus. scriptMenuActions. Every menuItem is connected to a menuAction through the associatedMenuAction property. Understanding the Menu Model The InDesign menu-scripting model is made up of a series of objects that correspond to the menus you see in the application’s user interface. A menu object contains the following objects: menuItems — The menu options shown on a menu. one. which associate a script with a menu selection. remove menu items.9 Menus InDesign scripting can add menu items. menuSeparators — Lines used to separate menu options on a menu. We assume that you have already read Adobe InDesign CS5 Scripting Tutorial and know how to create. submenus — Menu options that contain further menu choices. perform any menu command. eventListeners — These respond to user (or script) actions related to a menu. install. and attach scripts to menu items. The following diagram shows how the different menu objects relate to each other: 128 . events — The events triggered by a menu. menuElements — All menuItems. menuSeparators and submenus shown on a menu. including menus associated with panels as well as those displayed on the main menu bar.

. run the following script fragment (from the GetMenuActions tutorial script): var myMenuActionNames = app. To create a list (as a text file) of all menu actions. These scripts can be very slow.. } To create a list (as a text file) of all available menus. the result is null. myTextFile.everyItem().. eventListener eventListener . //If the user clicked the Cancel button. myCounter < myMenuActionNames. for(var myCounter = 0. } myTextFile..length. as there are many menu names in InDesign.menuActions. myCounter++){ myTextFile.saveDialog("Save Menu Action Names As". //Open a new text file. run the following script fragment (for the complete script.writeln(myMenuActionNames[myCounter]). see GetMenuNames).close().CHAPTER 9: Menus Understanding the Menu Model 129 application menuActions menuAction area checked enabled eventListeners id index label name events parent title scriptMenuActions scriptMenuAction same as menuAction event event .name.. undefined).open("w"). if(myTextFile != null){ //Open the file with write access. var myTextFile = File.

CHAPTER 9: Menus

Understanding the Menu Model

130

var myMenu; //Open a new text file. var myTextFile = File.saveDialog("Save Menu Action Names As", undefined); //If the user clicked the Cancel button, the result is null. if(myTextFile != null){ //Open the file with write access. myTextFile.open("w"); for(var myMenuCounter = 0;myMenuCounter< app.menus.length; myMenuCounter++){ myMenu = app.menus.item(myMenuCounter); myTextFile.writeln(myMenu.name); myProcessMenu(myMenu, myTextFile); } myTextFile.close(); alert("done!"); } function myProcessMenu(myMenu, myTextFile){ var myMenuElement; var myIndent = myGetIndent(myMenu); for(var myCounter = 0; myCounter < myMenu.menuElements.length; myCounter++){ myMenuElement = myMenu.menuElements.item(myCounter); if(myMenuElement.getElements()[0].constructor.name != "MenuSeparator"){ myTextFile.writeln(myIndent + myMenuElement.name); if(myMenuElement.getElements()[0].constructor.name == "Submenu"){ if(myMenuElement.menuElements.length > 0){ myProcessMenu(myMenuElement, myTextFile); } } } } } function myGetIndent(myObject){ var myString = "\t"; var myDone = false; do{ if((myObject.parent.constructor.name == "Menu")|| (myObject.parent.constructor.name == "Application")){ myDone = true; } else{ myString = myString + "\t"; myObject = myObject.parent; } }while(myDone == false) return myString; }

Localization and menu names
in InDesign scripting, menuItems, menus, menuActions,and submenus are all referred to by name. Because of this, scripts need a method of locating these objects that is independent of the installed locale of the application. To do this, you can use an internal database of strings that refer to a specific item, regardless of locale. For example, to get the locale-independent name of a menu action, you can use the following script fragment (for the complete script, see GetKeyStrings):

CHAPTER 9: Menus

Running a Menu Action from a Script

131

var myString = ""; var myMenuAction = app.menuActions.item("Convert to Note"); var myKeyStrings = app.findKeyStrings(myMenuAction.name); if(myKeyStrings.constructor.name == "Array"){ for(var myCounter = 0; myCounter < myKeyStrings.length; myCounter ++){ myString += myKeyStrings[myCounter] + "\r"; } } else{ myString = myKeyStrings; } alert(myString);

NOTE: It is much better to get the locale-independent name of a menuAction than of a menu, menuItem, or submenu, because the title of a menuAction is more likely to be a single string. Many of the other menu objects return multiple strings when you use the findKeyStrings method. Once you have the locale-independent string you want to use, you can include it in your scripts. Scripts that use these strings will function properly in locales other than that of your version of InDesign. To translate a locale-independent string into the current locale, use the following script fragment (from the TranslateKeyString tutorial script):
var myString = app.translateKeyString("$ID/NotesMenu.ConvertToNote"); alert(myString);

Running a Menu Action from a Script
Any of InDesign’s built-in menuActions can be run from a script. The menuAction does not need to be attached to a menuItem; however, in every other way, running a menuItem from a script is exactly the same as choosing a menu option in the user interface. For example, If selecting the menu option displays a dialog box, running the corresponding menuAction from a script also displays a dialog box. The following script shows how to run a menuAction from a script (for the complete script, see InvokeMenuAction):
//Get a reference to a menu action. var myMenuAction = app.menuActions.item("$ID/NotesMenu.ConvertToNote"); //Run the menu action. This example action will fail if you do not //have text selected. myMenuAction.invoke();

NOTE: In general, you should not try to automate InDesign processes by scripting menu actions and user-interface selections; InDesign’s scripting object model provides a much more robust and powerful way to work. Menu actions depend on a variety of user-interface conditions, like the selection and the state of the window. Scripts using the object model work with the objects in an InDesign document directly, which means they do not depend on the user interface; this, in turn, makes them faster and more consistent.

Adding Menus and Menu Items
Scripts also can create new menus and menu items or remove menus and menu items, just as you can in the InDesign user interface. The following sample script shows how to duplicate the contents of a submenu to a new menu in another menu location (for the complete script, see CustomizeMenu):

CHAPTER 9: Menus

Menus and Events

132

var myMainMenu = app.menus.item("Main"); var myTypeMenu = myMainMenu.menuElements.item("Type"); var myFontMenu = myTypeMenu.menuElements.item("Font"); var myKozukaMenu = myFontMenu.submenus.item("Kozuka Mincho Pro "); var mySpecialFontMenu = myMainMenu.submenus.add("Kozuka Mincho Pro"); for(myCounter = 0;myCounter < myKozukaMenu.menuItems.length; myCounter++){ var myAssociatedMenuAction = myKozukaMenu.menuItems.item(myCounter).associatedMenuAction; mySpecialFontMenu.menuItems.add(myAssociatedMenuAction); }

To remove the custom menu item created by the above script, use RemoveCustomMenu.
var myMainMenu = app.menus.item("$ID/Main"); try{ var mySpecialFontMenu = myMainMenu.submenus.item("Kozuka Mincho Pro"); mySpecialFontMenu.remove(); }catch(myError){}

Menus and Events
Menus and submenus generate events as they are chosen in the user interface, and menuActions and scriptMenuActions generate events as they are used. Scripts can install eventListeners to respond to these events. The following table shows the events for the different menu scripting components: Object
menu

Event
beforeDisplay

Description Runs the attached script before the contents of the menu is shown. Runs the attached script when the associated menuItem is selected, but after the onInvoke event. Runs the attached script when the associated menuItem is selected, but before the onInvoke event. Runs the attached script when the associated menuItem is selected, but after the onInvoke event. Runs the attached script when the associated menuItem is selected, but before the onInvoke event. Runs the attached script before an internal request for the enabled/checked status of the scriptMenuActionscriptMenuAction. Runs the attached script when the scriptMenuAction is invoked. Runs the attached script before the contents of the submenu are shown.

menuAction

afterInvoke

beforeInvoke

scriptMenuAction

afterInvoke

beforeInvoke

beforeDisplay

onInvoke

submenu

beforeDisplay

For more about events and eventListeners, see Chapter 8, “Events.” To change the items displayed in a menu, add an eventListener for the beforeDisplay event. When the menu is selected, the eventListener can then run a script that enables or disables menu items, changes

CHAPTER 9: Menus

Working with scriptMenuActions

133

the wording of menu item, or performs other tasks related to the menu. This mechanism is used internally to change the menu listing of available fonts, recent documents, or open windows.

Working with scriptMenuActions
You can use scriptMenuAction to create a new menuAction whose behavior is implemented through the script registered to run when the onInvoke event is triggered. The following script shows how to create a scriptMenuAction and attach it to a menu item (for the complete script, see MakeScriptMenuAction). This script simply displays an alert when the menu item is selected.
var mySampleScriptAction = app.scriptMenuActions.add("Display Message"); var myEventListener = mySampleScriptAction.eventListeners.add("onInvoke", function(){alert("This menu item was added by a script.");}); //If the submenu "Script Menu Action" does not already exist, create it. try{ var mySampleScriptMenu = app.menus.item("$ID/Main").submenus.item( "Script Menu Action"); mySampleScriptMenu.title; } catch (myError){ var mySampleScriptMenu = app.menus.item("$ID/Main").submenus.add ("Script Menu Action"); } var mySampleScriptMenuItem = mySampleScriptMenu.menuItems.add(mySampleScriptAction);

To remove the menu, submenu, menuItem, and scriptMenuAction created by the above script, run the following script fragment (from the RemoveScriptMenuAction tutorial script):
#targetengine "session" var mySampleScriptAction = app.scriptMenuActions.item("Display Message"); mySampleScriptAction.remove(); var mySampleScriptMenu = app.menus.item("$ID/Main").submenus.item ("Script Menu Action"); mySampleScriptMenu.remove();

You also can remove all scriptMenuAction, as shown in the following script fragment (from the RemoveAllScriptMenuActions tutorial script). This script also removes the menu listings of the scriptMenuAction, but it does not delete any menus or submenus you might have created.
#targetengine "session" app.scriptMenuActions.everyItem().remove();

You can create a list of all current scriptMenuActions, as shown in the following script fragment (from the ListScriptMenuActions tutorial script):

The following snippet adds a beforeDisplay eventListener which checks for the existence of a menuItem and removes it if it already exists. } scriptMenuAction also can run scripts during their beforeDisplay event.add(mySampleScriptAction).item("Display Message"). if(app. //If the user clicked the Cancel button.add("Display Message").open("w").selection. }).constructor.enabled = true. //Open a new text file.scriptMenuActions. Among other things. myTextFile. var myTextFile = File.eventListeners. myString = app.menuItems.add("onInvoke".everyItem(). } myTextFile. undefined). myCounter++){ myTextFile. in which case they are executed before an internal request for the state of the scriptMenuAction (e. the script in the eventListener disables the menu item. var mySampleScriptMenu = app. } }). for(var myCounter = 0.length > 0){ mySampleScriptAction. we add an eventListener to the beforeDisplay event that checks the current selection."). If there is no selection. The following snippet shows how to create a new menu item on the Layout context menu (the context menu that appears when you have a page item selected). mySampleScriptMenu.name.eventListeners. for the complete script.. var mySampleScriptAction = app.saveDialog("Save Script Menu Action Names As". and choosing the menu item displays the type of the first item in the selection.writeln(myScriptMenuActionNames[myCounter]). myCounter < myScriptMenuActionNames.CHAPTER 9: Menus A More Complex Menu-scripting Example 134 var myScriptMenuActionNames = app.scriptMenuActions.close().add("beforeDisplay".add("Script Menu Action"). the menu item is enabled. A More Complex Menu-scripting Example You have probably noticed that selecting different items in the InDesign user interface changes the contents of the context menus.enabled = false. (For the complete script.length.) var mySampleScriptAction = app. In the following sample script.selection[0]. the result is null. the script can then change the menu names and/or set the enabled/checked status. when the menu item is about to be displayed). function() { //JavaScript function to run before the menu item is drawns. If an item is selected. see LayoutContextMenu. We do this to ensure the menuItem does not appear on the context menu when the selection does not contain a . Fragments of the script are shown below. alert("The first item in the selection is a " + myString + ".g. } else{ mySampleScriptAction.scriptMenuActions. The following sample script shows how to modify the context menu based on the properties of the object you select. var myEventListener = mySampleScriptAction.item("$ID/Main"). see BeforeDisplay. function() { //JavaScript function to run when the menu item is selected.menus. if(myTextFile != null){ //Open the file with write access.name.submenus. var mySampleScriptMenuItem = mySampleScriptMenu.

} break. case "Rectangle": case "Oval": case "Polygon": if(app.selection.name){ case "PDF": case "EPS": case "Image": myObjectList.push(app.add("Create Graphic Label"). var myBeforeDisplayListener = myLayoutContextMenu. false).length > 0){ var myObjectList = new Array.item(0)).item("$ID/RtMouseLayout"). myBeforeDisplayHandler. //If a graphic is selected.selection[myCounter].menus. The eventListener then checks the selection to see if it contains a graphic. if(myCheckForMenuItem(myLayoutContextMenu. myCounter ++){ switch(app. myCounter < app.length != 0){ myObjectList. it creates a new scriptMenuItem. } } else{ //Remove the menu item. .menuItems. //Does the selection contain any graphics? for(var myCounter = 0. } } } } function myMakeLabelGraphicMenuItem(){ //alert("Got to the myMakeLabelGraphicMenuItem function!").documents.selection[myCounter]. "Create Graphic Label") == false){ myMakeLabelGraphicMenuItem(). var myLabelGraphicMenuAction = app. break. //The locale-independent name (aka "key string") for the //Layout context menu is "$ID/RtMouseLayout". if it exists.addEventListener ("beforeDisplay". default: } } if(myObjectList. //Create the event handler for the "beforeDisplay" //event of the Layout context menu.remove(). function myBeforeDisplayHandler(myEvent){ if(app. graphics.graphics.item("Create Graphic Label"). if so.selection[myCounter].selection. //This event handler checks the type of the selection. the event handler adds the script menu //action to the menu. and to avoid adding multiple menu choices to the context menu.length.length > 0){ //Add the menu item if it does not already exist.push(app. if(myCheckForMenuItem(myLayoutContextMenu.selection[myCounter]).scriptMenuActions.CHAPTER 9: Menus A More Complex Menu-scripting Example 135 graphic.constructor. var myLayoutContextMenu = app. if(myCheckForScriptMenuItem("Create Graphic Label") == false){ //alert("Making a new script menu action!").length != 0){ if(app. "Create Graphic Label") == true){ myLayoutContextMenu.

push(app.push(app. function myAddLabel(myGraphic.length > 0){ myDisplayDialog(myObjectList). false). var myDocument = app.scriptMenuActions. switch(myLabelType){ //File name case 0: myLabel = myLink. myLabelHeight. menuItems.menus. myLabelOffset.item(0)). case "Rectangle": case "Oval": case "Polygon": if(app.paragraphStyles.name.graphics.item(myLayerName). trying to get //the layer name will cause an error. //File path case 1: myLabel = myLink. var myLabel.add("onInvoke". break. } break.length.selection[myCounter]). break. //Does the selection contain any graphics? for(var myCounter = 0.name){ case "PDF": case "EPS": case "Image": myObjectList.selection. myLabelStyle = myDocument.length != 0){ myObjectList. eventListeners.filePath. myLabelLayer.layers.item("Create Graphic Label")). } var myLabelGraphicMenuItem = app. var myLink = myGraphic. myCounter ++){ switch(app.item (myLabelStyleName).add(myLayerName).constructor.layers.selection[myCounter]. if(app.documents.CHAPTER 9: Menus A More Complex Menu-scripting Example 136 var myLabelGraphicEventListener = myLabelGraphicMenuAction.length > 0){ var myObjectList = new Array.name. } } //Function that adds the label. myCounter < app. myLabelType.item("$ID/RtMouseLayout").selection[myCounter]. function myLabelGraphicEventHandler(myEvent){ //alert("Got to myLabelGraphicEventListener!"). //if the layer does not exist. } //Label type defines the text that goes in the label.selection[myCounter]. } catch (myError){ myLabelLayer = myDocument. try{ myLabelLayer = myDocument.selection.itemLink. .item(0). myLabelGraphicEventHandler. myLabelStyleName. myLayerName){ var myLabelLayer. graphics.add(app. default: } } if(myObjectList.

} } //Text frame height with(dialogRows.add()){ var myLabelTypeDropdown = dropdowns. "XMP description".geometricBounds[1]. undefined. } var myFrame = myGraphic.linkXmp. var myX2 = myFrame. var myTextFrame = myFrame.parent.textFrames.dialogColumns.item(0)).add( {stringList:["File name". myTextFrame.add .add({staticLabel:"Label Height". minWidth:myLabelWidth}). var myX1 = myFrame.textFramePreferences.".add()){ staticTexts. //XMP description case 2: try{ myLabel = myLink. with(myDialog. myY2.linkXmp. } with(dialogColumns.paragraphs.parent. minWidth:myLabelWidth}). "XMP author"]. var myStyleNames = myGetParagraphStyleNames (app.item(0).geometricBounds[2] + myLabelOffset.add(myLabelLayer.documents. } break.documents.add()){ //Label type with(dialogRows. var myY2 = myY1 + myLabelHeight.author } catch(myError){ myLabel = "No author available. myTextFrame. } catch(myError){ myLabel = "No description available.contents:myLabel}). } break. selectedIndex:0}).add({name:"LabelGraphics"}).add()){ with(dialogColumns.description. var myDialog = app.add({staticLabel:"Label Type".add()){ var myLabelHeightField = measurementEditboxes. //XMP author case 3: try{ myLabel = myLink.item(0)). myX1. undefined.leadingOffset.CHAPTER 9: Menus A More Complex Menu-scripting Example 137 break.geometricBounds[3]. } function myDisplayDialog(myObjectList){ var myLabelWidth = 100.firstBaselineOffset = FirstBaseline.add()){ staticTexts. } with(dialogColumns.appliedParagraphStyle = myLabelStyle. var myY1 = myFrame.add()){ with(dialogColumns.dialogs. "File path".".{geometricBounds:[myY1. myX2]. var myLayerNames = myGetLayerNames(app.

. var myLabelHeight = myLabelHeightField. } } } var myResult = myDialog.documents.add()){ staticTexts. selectedIndex:0}). myCounter < myObjectList.add()){ staticTexts.viewPreferences.add()){ with(dialogColumns.add ({editValue:0. myDialog.add({staticLabel:"Label Offset".add ({stringList:myLayerNames. myCounter++){ var myGraphic = myObjectList[myCounter]. horizontalMeasurementUnits.viewPreferences. editUnits:MeasurementUnits. minWidth:myLabelWidth}). } } //Style to apply with(dialogRows. if(myResult == true){ var myLabelType = myLabelTypeDropdown. var myLayerName = myLayerNames[myLayerDropdown.editValue. app.selectedIndex.points}).documents. } with(dialogColumns.editValue.add()){ var myLayerDropdown = dropdowns. } with(dialogColumns. } } //Text frame offset with(dialogRows.destroy().item(0).add()){ with(dialogColumns. var myOldYUnits = app.documents.item(0). minWidth:myLabelWidth}).documents.add()){ with(dialogColumns. } with(dialogColumns. } } //Layer with(dialogRows. editUnits:MeasurementUnits.add({staticLabel:"Layer:". verticalMeasurementUnits = MeasurementUnits. selectedIndex]. var myOldXUnits = app. app.points. verticalMeasurementUnits.viewPreferences.length. for(var myCounter = 0. selectedIndex].show().CHAPTER 9: Menus A More Complex Menu-scripting Example 138 ({editValue:24.add()){ var myLabelStyleDropdown = dropdowns.points.add ({stringList:myStyleNames.add()){ var myLabelOffsetField = measurementEditboxes. horizontalMeasurementUnits = MeasurementUnits. minWidth:myLabelWidth}).points}).item(0).item(0).add()){ staticTexts. selectedIndex:0}). var myLabelStyle = myStyleNames[myLabelStyleDropdown.add({staticLabel:"Label Style".viewPreferences. var myLabelOffset = myLabelOffsetField.

} else{ myDialog.item(0).destroy(). horizontalMeasurementUnits = myOldXUnits. verticalMeasurementUnits = myOldYUnits.CHAPTER 9: Menus A More Complex Menu-scripting Example 139 myAddLabel(myGraphic.viewPreferences. myLabelType. } app. app. myLabelOffset.documents. myLabelStyle.item(0). } } } } } .documents. myLayerName).viewPreferences. myLabelHeight.

placed images and PDF files). It can be run in the background as you work. Return as warning — The preflight rule returns warning-level feedback.name. Each data object has a name. which is read-only. For example. and run a script. } str += profiles. We briefly highlight how it is done in the user interface. there is one profile. There might be one or more preflight profiles. Exploring Preflight Profiles InDesign’s preflight feature is profile based. For illustration purposes. rule driven. fonts.length. 140 . i < profileCount.item(i).. see ListPreflightProfiles. This chapter demonstrates how to interact with the preflight system using scripting.g. if you placed an image as a low-resolution proxy but do not have the high-resolution original image accessible on your hard disk (or workgroup server). Return as error — The preflight rule returns error-level feedback. ".| str = "Preflight profiles: ". To check the profile in InDesign. etc. data type. that may result in an error during the printing process. [Basic]. (var i = 0. Preflight checks for this sort of problem. choose Preflight Panel > Define Profiles. printer settings. then show how to achieve the same results through scripting. You also can get profile information by scripting.5" x 11"). install. trapping styles. you cannot modify or delete it. A preflight profile contains many preflight rules. and parameterized.10 Working with Preflight Preflight is a way to verify that you have all required files.preflightProfiles. before you send a publication to an output device. i++) if (i != 0) { str += ". Each rule can be configured as follows: Disabled — The preflight rule is disabled. profileCount = profiles. Return as informational — The preflight rule returns informational-level feedback. We assume that you have already read Adobe InDesign CS5 Scripting Tutorial and know how to create. The data value can be changed.. Each rule has a name and multiple data objects. we show how to configure preflight to raise an error if the page size is something other than letter size (8. Listing preflight profiles This script fragment shows how to list all preflight profiles. For the complete script. and data value. Initially. } alert(str). var var var for { profiles = app. assets (e.

name. "." + myRule.item(0). } .CHAPTER 10: Working with Preflight Exploring Preflight Profiles 141 Listing preflight rules This script fragment shows how to list all preflight rules in a profile.length. Listing preflight data objects This script fragment shows how to list all preflight data objects in a profile rule.BOOLEAN_DATA_TYPE) { return "Boolean".item(0).preflightProfileRules.length. var ruleCount = myRules.dataValue. } alert(str).item(i).item(i). i++) { if (i > 0) { str += ". str += dataObjects. see ListPreflightRules. // Assume the [Basic] profile exists var myProfile = app. see ListPreflightDataObjects. } alert(str). // rule ADBE_BlankPages var myRule = myProfile.item(0). ". var dataObjectCount = dataObjects.preflightProfileRules.ruleDataObjects. var str = "Preflight rules of " + myProfile. } else if (type == RuleDataType. var myRules = myProfile. ". } str += myRules.name + ". function getDataObjectDataType(type) { if (type == RuleDataType. var dataObjects = myRule. var str = "Preflight rule data objects of " + myProfile.item(i). for (var i = 0.item(i).preflightProfiles. for (var i = 0. i < ruleCount. // Assume the [Basic] profile exists.dataType) + ".preflightProfiles.name + ". i++) { if (i > 0) { str += ".name + ": ". var myProfile = app. For the complete script. } str += dataObjects.INTEGER_DATA_TYPE) { return "Integer". str += getDataObjectDataType(dataObjects. i < dataObjectCount. } else if (type == RuleDataType. For the complete script.name + ": ". ".LIST_DATA_TYPE) { return "List".

STRING_DATA_TYPE) { return "String". .OBJECT_DATA_TYPE) { return "Object". } else { return type. then choose Load Profile from the drop-down menu in the Preflight Profiles window. } } Importing a Preflight Profile To import a preflight profile from the Preflight panel. choose Preflight Panel > Define Profiles. } else if (type == RuleDataType.CHAPTER 10: Working with Preflight Importing a Preflight Profile 142 else if (type == RuleDataType.SHORT_INTEGER_DATA_TYPE) { return "Short Integer". } else if (type == RuleDataType.REAL_DATA_TYPE) { return "Real". } else if (type == RuleDataType.

CHAPTER 10: Working with Preflight Creating a Preflight Profile 143 You also can load a profile with scripting.idpp")).name + " is loaded. then choose the plus sign (+) to add a new preflight profile. and import them using scripting. export them to files. if (myProfile == null) { alert("The profile did not load successfully"). see ImportPreflightProfile. The following script fragment adds a single profile called Test. } else { alert("Preflight profile " + myProfile. see CreatePreflightProfile.loadPreflightProfile(File("/c/Test. . One workflow would be to create all profiles in the user interface.") } It is easier to create profiles using the Preflight panel than with scripting. choose Preflight Panel > Define Profiles. var myProfile = app. For the complete script. You also can create a profile with scripting. For the complete script. The following script fragment imports a profile called Test. Name the profile and fill in all data values for the available rules. Creating a Preflight Profile To create a preflight profile from the Preflight panel. This approach avoids the challenges involved with manually adding rules via scripting.

For information on rule names.description = "Test description". or check to see if a profile exists and remove it. } } Adding Rules A preflight profile contains a mutually exclusive set of rules.preflightProfiles.remove(). 2. alert("Preflight profile " + oldName + " is renamed to " + myProfile. rules have data properties.preflightProfiles. The ADBE_PageSizeOrientation rule contains particular data properties that allow you to specify a page size.itemByName(name). . var myRule = myProfile.add().itemByName(). To avoid this. For a complete specification of the rules available with InDesign.add(RULE_NAME). To add a rule to a profile. Rules are added by name. Set the rule’s data values. indicating that a profile with that name already exists. but not all. an error is raised. var oldName = myProfile. if (myProfile == null) { alert("The profile did not add successfully").name myProfile. } else { alert("Preflight profile " + myProfile. The following adds the ADBE_PageSizeOrientation rule to the profile. //If a profile with that name was found if (oldProfile != null) { oldProfile. If the script above is executed more than once within the same InDesign instance.preflightProfileRules.") Preflight-profile names must be unique. const RULE_NAME = "ADBE_PageSizeOrientation".name + " is added.preflightProfiles. For the complete script.CHAPTER 10: Working with Preflight Adding Rules 144 //Add a new preflight profile var myProfile = app. //Add a rule that requires a specific page size and orientation //(portrait or landscape). The following sets the acceptable page height and width.") } //Rename the profile. Many. either access the existing profile using app.name + ". see the following script fragment. a tolerance (fudge factor). see DeletePreflightProfile. Add a rule to a profile by name. and an option for handling page orientation. function removeProfile(name) { //Lookup the existing preflight profile by name var oldProfile = app. see “Available Rules” on page 146. see “Available Rules” on page 146. myProfile. follow these steps: 1.name = "Test".

) If there are errors.5 inches myRule.preflightProcesses. In scripting (especially for InDesign Server). and error). RuleDataType. //Process the myDoc with the rule var myProcess = app.5in x 11in (Letter Size) //enters a value for tolerance myRule.ruleDataObjects.add("width". .realDataType.item(0). // Assume the Test preflight profile exists. myProfile).ruleDataObjects. RuleDataType. There are several choices (disabled.add("tolerance".01).add(myDoc. //set the rule to return an error myRule. 3.add("height".returnAsError. the errors are generated on demand. controlled by the PreflightRuleFlag enumeration. var myProfile = app. var myResults = myProcess.waitForProcess(). preflight errors are reported in the user interface. Processing a Profile In the desktop version of InDesign. //Sets the width to the point equivalent of 11 inches myRule. information. see ProcessPreflightProfile. true).ruleDataObjects.ruleDataObjects. 792). var myDoc = app.saveReport(File("C:\PreflightResults. RuleDataType.flag = PreflightRuleFlag.itemByName("Test").pdf"). For an example of the output. //true = ignore orientation is checked myRule.booleanDataType. myProcess. //If errors were found if (myResults != "None") { //Export the file to PDF.realDataType. The following script processes an InDesign document. // Assume there is a document.processResults.add("ignore_orientation". Set the rule’s reporting state. 0. see the figure below the script. warning. 612). //Sets the width to the point equivalent of 8.remove(). } //Cleanup myProcess. myProcess. true). RuleDataType.documents. (For the complete script. This is done using the rule’s flag property.preflightProfiles.CHAPTER 10: Working with Preflight Processing a Profile 145 //Requires the page size to be 8. The "true" value selects to open the file after export. it writes the results to a new PDF file.realDataType.

length. PreflightRule. .CHAPTER 10: Working with Preflight Custom Rules 146 If you would rather produce a text file. that demonstrates how to add custom rules with a plug-in. Results: [" var errorResults = errors[2] for (var i = 0. you may prefer to iterate the errors yourself.jsx script is provided in the SDK to produce the following output as an HTML file (SDK\docs\references\PreflightRules. var str = "Document: " + errors[0] + ". For the complete script. you can run the script to extract the new names and properties. The following demonstrates how to access the errors array. Profile: " + errors[1] + ". see “Exploring Preflight Profiles” on page 140.aggregatedResults // Show the errors in a message box. the DumpPreflightRules. " } str += errorResults[i][1] } str = str + "]" alert(str) } Custom Rules It is not possible to create custom rules through the Preflight panel or scripting. this can be done through a C++ plug-in. i < errorResults. simply name your output file with a . however. specific rule names and properties do not appear in the Extend Script Tool Kit’s Object Model Viewer. If you use a plug-in that adds custom rules. //If errors were found if (myResults != "None") { // array containing detailed results var errors = myProcess. see ProcessPreflightProfileShowErrors.txt extension.html). For your convenience. The InDesign Products SDK contains a sample. Available Rules One of the hardest aspects of scripting rules is discovering rule names and properties. Alternately. Due to the dynamic nature of rules (they really are just strings). i++) { if (i > 1) { str += ". To discover this information.

CHAPTER 10: Working with Preflight Available Rules 147 Rule name ADBE_BlankPages ADBE_BleedSlug ADBE_BleedTrimHazard ADBE_CMYPlates ADBE_Colorspace ADBE_ConditionIndicators ADBE_CrossReferences ADBE_FontUsage ADBE_ImageColorManagement ADBE_ImageResolution ADBE_InteractiveContent ADBE_LayerVisibility ADBE_MissingFonts ADBE_MissingGlyph ADBE_MissingModifiedGraphics ADBE_OPI ADBE_Overprint ADBE_OversetText ADBE_PageCount ADBE_PageSizeOrientation ADBE_Registration ADBE_ScaledGraphics ADBE_ScaledType ADBE_SmallText ADBE_SpellCheck ADBE_SpotColorSetup ADBE_StrokeRequirements ADBE_TextOverrides ADBE_TransparencyBlending Rule properties “ADBE_BlankPages” on page 148 “ADBE_BleedSlug” on page 148 “ADBE_BleedTrimHazard” on page 149 no “ADBE_Colorspace” on page 149 no “ADBE_CrossReferences” on page 149yes “ADBE_FontUsage” on page 150 “ADBE_ImageColorManagement” on page 150 “ADBE_ImageResolution” on page 150 no no no no no no no no “ADBE_PageCount” on page 151 “ADBE_PageSizeOrientation” on page 151 no “ADBE_ScaledGraphics” on page 151 “ADBE_ScaledType” on page 151 “ADBE_SmallText” on page 152 no “ADBE_SpotColorSetup” on page 152 “ADBE_StrokeRequirements” on page 152 “ADBE_TextOverrides” on page 152 “ADBE_TransparencyBlending” on page 152 .

CHAPTER 10: Working with Preflight Available Rules 148 Rule name ADBE_TransparencyUsage ADBE_WhiteOverprint Rule properties no no ADBE_BlankPages Data Type Boolean Boolean Name ignore_master ignore_nonprinting Default value true true ADBE_BleedSlug Data Type Real Real Integer Boolean Real Real Real Real Real Real Real Real Integer Boolean Real Real Real Real Real Name bleed_b bleed_b_aux bleed_comparison_type bleed_enabled bleed_l bleed_l_aux bleed_r bleed_r_aux bleed_t bleed_t_aux slug_b slug_b_aux slug_comparison_type slug_enabled slug_l slug_l_aux slug_r slug_r_aux slug_t Default value 9 9 3 true 9 9 9 9 9 9 18 18 3 false 18 18 18 18 18 .

01 ADBE_BleedTrimHazard Data Type Boolean Real Real Real Real Real Real Name binding_enabled binding_width live_b live_l live_r live_t tolerance Default value false 1 18 18 18 18 0.01 ADBE_Colorspace Data Type Boolean Boolean Boolean Boolean Boolean Name no_cmyk no_gray no_lab no_rgb no_spot Default value false false false false false ADBE_CrossReferences Data Type Boolean Boolean Name xrefs_out_of_date xrefs_unresolved Default value true true .CHAPTER 10: Working with Preflight Available Rules 149 Data Type Real Real Name slug_t_aux tolerance Default value 18 0.

CHAPTER 10: Working with Preflight Available Rules 150 ADBE_FontUsage Data Type Boolean Boolean Boolean Boolean Boolean Boolean Boolean Boolean Boolean Boolean Name no_ATC no_Bitmap no_CID no_MultipleMaster no_OpenTypeCFF no_OpenTypeCID no_OpenTypeTT no_TrueType no_Type1 no_protected Default value false false false false false false false false false true ADBE_ImageColorManagement Data Type Boolean Boolean Boolean Name no_cmyk_profiles no_image_overrides overrides_exclude_uncal Default value true true true ADBE_ImageResolution Data Type Boolean Real Boolean Real Boolean Real Boolean Real Boolean Name bw_max_enabled bw_max_res bw_min_enabled bw_min_res color_max_enabled color_max_res color_min_enabled color_min_res gray_max_enabled Default value false 2400 true 800 false 1200 true 250 false .

CHAPTER 10: Working with Preflight Available Rules 151 Data Type Real Boolean Real Real Name gray_max_res gray_min_enabled gray_min_res tolerance Default value 1200 true 250 0.5 .5 ADBE_ScaledType Data Type Boolean Real Name ignore_justification max_scale Default value true 100.5 ADBE_PageCount Data Type Integer Integer Integer Name comparison_type comparison_value comparison_value_aux Default value 2 1 1 ADBE_PageSizeOrientation Data Type Real Boolean Real Real Name height ignore_orientation tolerance width Default value 792 false 0.01 612 ADBE_ScaledGraphics Data Type Real Name max_scale Default value 100.

CHAPTER 10: Working with Preflight Available Rules 152 ADBE_SmallText Data Type Real Boolean Name minSize minSize_trap_safe_only Default value 4 false ADBE_SpotColorSetup Data Type Boolean Boolean Integer Boolean Name lab_spots lab_spots_enabled max_spots max_spots_enabled Default value true false 1 true ADBE_StrokeRequirements Data Type Real Boolean Name min_width min_width_trap_safe_only Default value 0.125 false ADBE_TextOverrides Data Type Boolean Boolean Boolean Boolean Name ignore_color_overrides ignore_font_overrides ignore_kerning_tracking_overrides ignore_language_overrides Default value false false false false ADBE_TransparencyBlending Data Type Integer Name space Default value 3 .

Importing Movies and Sounds InDesign can import movie and sound files that can then be viewed or listened to in exported PDF. 72. //Add a preview image. however. You can also add a preview. You'll have to provide a valid path on your system. [72.embedInPDF = true. myMovie. movies. documents can include animations.mp3").11 Creating Dynamic Documents InDesign can create documents for web and online use. mySound. you cannot see (or hear) the content of the imported multimedia files on an InDesign page. Unlike graphics.doNotPrintPoster = true. //Import a movie file (you'll have to provide a valid file path on your system). For that. see the next section. mySound.add({geometricBounds:[72.” image to the page item containing the sound or movie. 288. 288]}). hyperlinks. or “poster. animations. mySound.jpg"). then open the file in a viewer capable of displaying the content (such as Acrobat Reader or a web browser).. //Import a sound file (you'll have to provide a valid file path on your system). Dynamic documents contain sounds. //Set sound properties. mySound.flv"))[0]. The following script fragment shows how to import a movie and control the way that the movie is shown and played in an exported document (for the complete script. 72])[0]. SWF.rectangles. var myFrame = myPage. Scripts can control the playback properties of a sound or movie in an exported dynamic document. and XFL. //Given a page "myPage". Buttons can be used to control the playback of sounds and movies.embedInPDF = true. myMovie. buttons. 153 . and other interactive content..place(File("/c/sound.posterFile = File("/c/movie poster. multistate objects. refer to the “Working with Documents” chapter. For SWF and XFL files. The following script fragment shows how to import a sound file and control the playback and display of the sound in an exported document (for the complete script. InDesign documents can be exported to SWF. //Set movie properties. This chapter shows how to create dynamic documents using scripting. you'll need to either view the page in the Preview panel. or PDF. For more on exporting as PDF. refer to PlaceMovie). You can use the Preview panel in InDesign to test some types of dynamic content before exporting. //Add a preview image. or XFL documents.soundLoop = true. Movies and sounds in an InDesign document are very similar to graphics in that they exist inside container objects on an InDesign page. refer to PlaceSound)..jpg").. var myMovie = myFrame. //Given a page "myPage". You'll have to provide a valid path on your system. SWF. var mySound = myPage. also known as Rich Interactive Documents (RID). mySound.stopOnPageTurn = true. and sound clips. myMovie. XFL. or export the file.posterFile = File("/c/sound poster.place(File("/c/movie. For information on how to script buttons.showControls = true.

var myGoToNextPageBehavior = myButton. text frames.polygons.” and “Click. Behaviors correspond to the Actions shown in the Buttons panel in InDesign’s user interface..mouseUp}). 144.item(0).[144. 72].add({fillColor:myDocument.108].item("Red"). Buttons can contain multiple behaviors. var myRightArrow = myPage.add({geometricBounds:[72. can contain page items such as rectangles.[72. The button can display only one state at a time. ovals. The following script fragment shows how to create a simple button that displays the next page in an exported PDF or SWF (for the complete script. 144]}).states.buttons. myButton.CHAPTER 11: Creating Dynamic Documents Creating Buttons 154 Creating Buttons Buttons are often used for navigation in dynamic documents.colors. This button makes use of only the Normal state.. in turn. 144]].paths. myRightArrow. refer to ButtonStates.add({behaviorEvent:BehaviorEvents. Behaviors control what the button does when you perform a specific mouse action. the other states are displayed when triggered by mouse actions.addItemsToState(myRightArrow). .gotoNextPageBehaviors. known as “Normal. For the complete script. 72.” “Rollover.item(0). var myButton = myPage. containing page items that change the appearance of each of the three button states. //Make a button by converting a page item. Buttons contain three states. //Given a page "myPage" and a document containing the color "Red". refer to SimpleButton). name:"GoToNextPageButton"}).entirePath = [[72.” which. or images. The following script fragment shows how to create a somewhat more complicated button.

dropShadowSettings.[282. myFillTransparencySettings.entirePath = [[72.size = 6.polygons.mode = ShadowMode.fillTransparencySettings.item("Red")}). //Add the Rollover state. myFillTransparencySettings.add({fillColor:myDocument. myRightArrow.colors. var myRolloverState = myPlayButton.entirePath = [[186.[282.dropShadowSettings.polygons.add({geometricBounds:[72.item("Red")}). var myClickArrow = myClickState.states.mouseUp}).item(0).dropShadowSettings.states. myClickArrow.item("Red")}). var myFrame = myPage.drop. var myGoToNextPageBehavior = myButton.colors.paths.[72.[144.[72.[186. myFillTransparencySettings.colors. 144]].add({geometricBounds:[294. 72]. 294].states.[72.entirePath = [[72.[144.colors. //Import a movie file (you'll have to provide a valid file path on your system). //Add a shadow to the polygon in the Rollover state.item(0).polygons." //containing the colors "Gray" and "Red". var myRightArrow = myButton. var myRolloverArrow = myRolloverState.angle = 90.dropShadowSettings.dropShadowSettings.buttons.drop.add({geometricBounds:[72.mode = ShadowMode. //Add a shadow to the polygon in the Click state. 72.282]. 288]}). 144]. myFillTransparencySettings.yOffset = 0.entirePath = [[72.354. var myClickState = myButton.354]. The following script fragment shows an example of using a set of buttons to control the playback of a moving file (for the complete script.gotoNextPageBehaviors. var myFillTransparencySettings = myRolloverArrow." containing the colors //"Blue" and "Red". . myFillTransparencySettings.add().. //Add a shadow to the polygon in the Click state. //Given a page "myPage" in a document "myDocument.item(0).item("Gray")}).354].108].dropShadowSettings. var myPlayButton = myPage.states. //Set the behavior for the button. myFillTransparencySettings.add().states.item("Blue")}).. 72.item(0). 72].. myFillTransparencySettings. 72].dropShadowSettings.yOffset = 0.add({fillColor:myDocument..CHAPTER 11: Creating Dynamic Documents Creating Buttons 155 //Given a page "myPage" in a document "myDocument.add().colors. Buttons can be used to control the playback of movie and sound files. 144]].add({behaviorEvent:BehaviorEvents. var myFillTransparencySettings = myRolloverArrow.polygons. myFillTransparencySettings.108].size = 6.item(0). 144.angle = 90. 324]]. //Create the movie "Start" button. myFillTransparencySettings.paths. 288. 294]. //Add a shadow to the polygon in the Rollover state. var myClickArrow = myClickState.[186.entirePath = [[186.paths." var myButton = myPage.dropShadowSettings.place(File("/c/movie.dropShadowSettings.add({fillColor:myDocument.buttons.paths. name:"PlayMovieButton"}). var myClickState = myPlayButton.dropShadowSettings.add({fillColor:myDocument. 144]]. myFrame.add().paths.[144. refer to MovieControl). //Add the Rollover state. myRightArrow. var myRolloverArrow = myRolloverState.polygons.polygons.108].add({fillColor:myDocument.186. myRolloverArrow. myRolloverArrow. myFillTransparencySettings. var myRightArrow = myPlayButton.rectangles.colors.item(0).flv")).add({fillColor:myDocument. name:"GoToNextPageButton"}).xOffset = 0.states.item(0). var myRolloverState = myButton.xOffset = 0. 324]].fillTransparencySettings.item("Gray")}). //Make a button "from scratch.

mouseUp.movieBehaviors. Creating Multistate Objects Multistate objects (or MSOs) are similar to buttons in that they contains states. var myNormalRectangle = myStopButton.yOffset = 0.states. var myStopButton = myPage.add({geometricBounds:[294.stop}).movieBehaviors.mode = ShadowMode.78.buttons. operation:MoviePlayOperations.size = 6.rectangles. refer to MakeMultiStateObject).fillTransparencySettings. at most.354.dropShadowSettings.entirePath = [[186.78.movies. myFillTransparencySettings.354. myFillTransparencySettings. .colors. var myClickRectangle = myClickState.item("Gray")}).add().add({movieItem:myFrame. behaviorEvent:BehaviorEvents. fillColor:myDocument.rectangles.CHAPTER 11: Creating Dynamic Documents Creating Multistate Objects 156 myClickArrow.174].states.rectangles.174]. myFillTransparencySettings. behaviorEvent:BehaviorEvents. var myMovieStopBehavior = myStopButton.174].354].[186. name:"StopMovieButton"}).play}).colors.states. Multistate objects rely on buttons to change the way they display their states.78.dropShadowSettings. 294].item(0). //Set the behavior for the button.paths.add({geometricBounds:[294. They are unlike buttons in that they can contain any number of states. 324]].354.item("Red")}). fillColor:myDocument.add({geometricBounds:[294.item(0). var myFillTransparencySettings = myRolloverRectangle.add({movieItem:myFrame. as we’ll demonstrate in the next section. and that only one state can be visible at a time.colors.item("Gray")}).item(0). var myMovieStartBehavior = myPlayButton.dropShadowSettings.dropShadowSettings.354.xOffset = 0. buttons can contain three states.add({geometricBounds:[294. Buttons are also important in controlling the appearance of multistate objects.[282. myRolloverState = myStopButton.mouseUp.174]. myFillTransparencySettings. The following script fragment shows how to create a simple multistate object and add a button to control the display of the states in the object (for the complete script. fillColor:myDocument.add().drop. myFillTransparencySettings.item(0).angle = 90.dropShadowSettings. myClickState = myStopButton.movies. //Create the movie "Stop" button.78. var myRolloverRectangle = myRolloverState. operation:MoviePlayOperations.

myPolygon.swatches.polygons. [144.states. myPolygon.entirePath = [[72.item(3). //Given a document "myDocument" and a page "myPage" and //four colors "myColorA.add({fillColor:myColorD. myPolygon.item("None")}).polygons.entirePath = [[72.add({fillColor:myColorB." and "myColorD". //Add page items to the states.add({fillColor:myColorD.item(0).swatches.swatches.item(0).swatches.. .. refer to MultiStateObjectControl). 108]].multiStateObjects.item(1).item(0).states.entirePath = [[144. Add two more. myPolygon = myMSO. myMSO. myMSO. var myPolygon = myMSO. 72]. Typically.item(0).add({name:"Left"}). 144]..add({fillColor:myColorB. 144]." and "myColorD".paths.add({fillColor:myColorA.states. 144].item(0).states.multiStateObjects.item(0).states. 72]]. 72]]. var myPolygon = myMSO. [144.states. [144. 144]}). 144]. myPolygon = myMSO. myPolygon = myMSO. 72.states.add({name:"Down"}). strokeColor:myDocument. [72.polygons. The following script fragment shows how to do this (for the complete script. 144. Add two more.states. //Add two more states. myMSO.item("None")}). strokeColor:myDocument. myMSO. 144]]. [144. [144. myPolygon = myMSO.swatches. //Add page items to the states. 144]].paths. 144]. [144. strokeColor:myDocument. strokeColor:myDocument.add({fillColor:myColorC. 108].item(0).paths. strokeColor:myDocument. 144].item("None")}).paths.states.item(0). myPolygon. 108]. myPolygon. //New multistate objects contain two states when they're created.entirePath = [[72. 72]. 72].item(1).name = "Up". myPolygon. 72]].item("None")}). 72. [108.polygons.name = "Right".add({name:"Down"}).item(0)." "myColorC.polygons.entirePath = [[72. //New multistate objects contain two states when they're created.polygons. myMSO.item(2).states.item(2).item(1).states.item("None")})." "myColorC. 72]. strokeColor:myDocument.states. [108. [144.states.entirePath = [[72.item(3).entirePath = [[72.add({name:"Spinner".paths. [72.states. myMSO.name = "Right". [72. strokeColor:myDocument. [108. myPolygon. 144]. 144.CHAPTER 11: Creating Dynamic Documents Creating Multistate Objects 157 //Given a document "myDocument" and a page "myPage" and //four colors "myColorA. myPolygon. geometricBounds:[72. [144. 144]}).item("None")}).item("None")}). myMSO.item("None")}).add({fillColor:myColorA. //Add two more states. strokeColor:myDocument.add({name:"Spinner".paths.entirePath = [[144. myPolygon = myMSO. myMSO. you’ll control the display of the states in a multistate object using a button.item(0).states. 72].polygons." "myColorB. geometricBounds:[72.item(1)." "myColorB.states.swatches.item(0).name = "Up". var myMSO = myPage. myPolygon = myMSO. [108.add({fillColor:myColorC. 72]. 144].add({name:"Left"}). 72]].swatches..polygons. [72.item(0).paths.paths. 108]]. var myMSO = myPage.swatches.

We havent' set a dynamic trigger //for the animation. relative to the event that triggers the animation.dropShadowSettings.true].add().[108. myFillTransparencySettings. TimingSettings The timingSettings objects of spreads. //Add a page items to animate. var myClickState = myButton. 144]. var myMotionPathPoints = [[[[108. 108]].item("None")}). if the object is not to be animated. enableBehavior:true. refer to SimpleAnimation). myPolygon.add({geometricBounds:[72. timingSettings contain: . The point at which an animation begins to play. is controlled by the objects and properties of the timingSettings object attached to the page item or to one of its parent containers (usually the spread). You apply animation to objects using motion presets.size = 6.[516. adding motion to the dynamic documents you create using InDesign.[[516. 144]}). and control the duration of the animation using timing settings.animationSettings.entirePath = [[72.CHAPTER 11: Creating Dynamic Documents Working with Animation 158 var myButton = myPage. 108]. strokeColor:myDocument.onPageLoad (the default). //Create a motion path. //Set animation preferences for the polygon. and page items control the timing of the animation(s) applied to the object and to any objects contained by the object. pages..states.mode = ShadowMode.duration = 2.paths.add({associatedMultiStateObject:myMSO. define the movement of animated objects using motion paths. so the polygon's animation will be triggered by //DynamicTriggerEvents.angle = 90.dropShadowSettings. When animation settings have been applied to an object. [72.yOffset = 0. myPolygon. var myFillTransparencySettings = myRolloverRectangle. myFillTransparencySettings.item(0). InDesign sets the hasCustomSettings property of the object to true. var myNextStateBehavior = myButton. [144.108]]. 144]}). myFillTransparencySettings. 108]. loopsToNextOrPrevious:true}). this property is false. 72. myFillTransparencySettings. The most basic forms of animation can be applied without using timing settings.add({geometricBounds:[72.add().dropShadowSettings. The animationSettings of an object control the animation that will be applied to the object. //Given a document "myDocument" and a page "myPage" and a color "myColorA". timing lists. myFillTransparencySettings.dropShadowSettings. 72. myPolygon. var myPolygon = myPage.swatches.108].strokeTransparencySettings. myRolloverState = myButton.drop.polygons. 144.add({fillColor:myColorA.motionPathPoints = myMotionPathPoints.gotoNextStateBehaviors. var myRolloverRectangle = myRolloverState.. 108]]]. and timing groups.rectangles.buttons.animationSettings. 144. 72].108].xOffset = 0. Working with Animation Page items can be animated.dropShadowSettings.[516. Basic animation The following script fragment shows how to create a simple animation (for the complete script.mouseDown.[108. behaviorEvent:BehaviorEvents.states.

144]. var myPolygonA = myPage.animationSettings. and so on) that start the animation.animationSettings.timingSettings. myPolygonB.swatches.onPageLoad. relative to the start of the animation of the timingGroup (for the first item in the timingGroup).paths. [72. myTimingGroup.polygons. Note that attempting to add a page item whose hasCustomSettings property (in the animationSettings object of the page item) is false to a timingTarget generates an error.item(0). The following script fragment shows how to control the timing of the animation of an object using the various timing objects (for the complete script.duration = 2. such as DynamicTriggerEvents. 108].add(DynamicTriggerEvents.add(myPolygonC. var myMotionPathPoints = [[[[108. such as DynamicTriggerEvents.[[516. refer to TimingSettings). myPolygonA. 72].timingLists.motionPathPoints = myMotionPathPoints. 2). page click. myPolygonA.add(myPolygonB.. 144]. which define the objects associated with a given timingGroup. myTimingGroup. For example.[516.duration = 2. 0). var myTimingGroup = myTimingList.animationSettings.duration = 2.paths. others.timingTargets.motionPathPoints = myMotionPathPoints. [72.swatches. 108]]. trigger the animations one by one. var myPolygonC = myPage.parent. timingTargets also specify a delay value for the animation applied to the page item. //Remove the default timing list. each containing a single . myPolygonB. strokeColor:myDocument.motionPathPoints = myMotionPathPoints. //Add a page items to animate. var myPolygonB = myPage. //Add the polygons to a single timing group.item(0). //Add a new timing list that triggers when the page is clicked.polygons.onPageClick.animationSettings. var myTimingList = myTimingSettings. 108].item(0).paths. can be added separately. [72. 144]. //"myColorB"..entirePath = [[72.entirePath = [[72.add({fillColor:myColorA.item("None")}). [144. or from the start of the previous item in the timingGroup (for other items in the timingGroup). in sequence. [144. Note that the parameters used to create a timingGroup specify the properties of the first timingTarget in the timingGroup.108].entirePath = [[72. 72].[108.true]. var myTimingSettings = myPage. [144. Note that the order in which timingGroups are added to a timingList determines the order in which the animations play when the trigger event specified in the timingList occurs. myPolygonC. timingGroups contain timingTargets. //Create a motion path. //Set animation preferences for the polygons. subsequent timingTargets.remove(). refer to MultipleTimingGroups). if any. 108]]].CHAPTER 11: Creating Dynamic Documents Working with Animation 159 timingLists.timingTargets.onPageClick). with each instance of the event. 2). a timingList containing five timingGroups.[108. 72]. Some trigger events.108].animationSettings. trigger the animations in the timingList (in sequence).timingLists.swatches. myPolygonC.item(0). myPolygonB. The following script fragment shows how to control the sequence of animations applied to objects on a page (for the complete script. //Given a document "myDocument" and a page "myPage" and the color "myColorA". strokeColor:myDocument. strokeColor:myDocument. myTimingSettings.timingGroups. timingGroups.108]].item("None")}).polygons. and "myColorC". which associate a page item or series of page items with a specific timing and define the sequence in which animations are shown.item("None")}).add(myPolygonA.add({fillColor:myColorB. myPolygonA.add({fillColor:myColorC.[516. 108]].animationSettings. 108]]. myPolygonC. which define the trigger event (page load.

108]].item(0). and having the trigger event DynamicTriggerEvents.animationSettings. var myMotionPathPointsA = [[[[108. [72. var myTimingGroupA = myTimingList. myPolygonF. 108].item(0). var myPolygonD = myPage.paths.timingGroups. //Given a document "myDocument" and a page "myPage" and the color "myColorA". 108]]. 108]]]. myPolygonE. 216].motionPathPoints = myMotionPathPointsA.add({fillColor:myColorC.animationSettings.swatches.polygons. 144]. 180]] var myPolygonF = myPage. 144].paths. 108].180].timingLists. [72.add(myPolygonF.add(myPolygonE. and "myColorC". 216].timingLists. 144]. myPolygonB. myTimingGroupB.entirePath = [[72. myTimingGroupA. myPolygonF. //Set animation preferences for the polygons. //Add a new timing list that triggers when the page is clicked. A given timingSettings object can contain multiple timingList objects. 72].entirePath = [[72.onPageClick requires five mouse clicks to process all the animations. //Add a page items to animate.duration = 2. [72.true].timingTargets. [72.true].paths. [144.add({fillColor:myColorB.animationSettings.add(myPolygonB. 0). 180]]]. //myTimingGroupB will play on the second page click.swatches.animationSettings.item(0).swatches.[516. 2).timingSettings.swatches. [144.motionPathPoints = myMotionPathPointsA. myPolygonD. 144]. //"myColorB".item("None")}).paths. //Add the polygons to a single timing group.motionPathPoints = myMotionPathPointsB. myPolygonA.duration = 2.onPageClick).item("None")}).paths. 180]]. [144. strokeColor:myDocument.polygons.add({fillColor:myColorA. strokeColor:myDocument. [144.polygons. 2).polygons.swatches. strokeColor:myDocument..parent. myTimingSettings. strokeColor:myDocument. 216]. strokeColor:myDocument. myPolygonF. 2).polygons.animationSettings. 0). 72].item("None")}).animationSettings. myPolygonC. strokeColor:myDocument. [72. //DynamicTriggerEvents. each of which responds to a different trigger event.motionPathPoints = myMotionPathPointsA.item(0).motionPathPoints = myMotionPathPointsB.[108.entirePath = [[72. myPolygonE.add({fillColor:myColorB.timingTargets.add({fillColor:myColorA. 144]. var myPolygonE = myPage. myPolygonB.duration = 2.entirePath = [[72.add(DynamicTriggerEvents.108]].item(0).item("None")}).paths.swatches. myPolygonC. 180].animationSettings.180].CHAPTER 11: Creating Dynamic Documents Working with Animation 160 timingTarget.108].add(myPolygonA.item("None")}). var myPolygonB = myPage. var myTimingSettings = myPage.[516. 108]].polygons. The following script fragment shows a series of animations triggered by .animationSettings.entirePath = [[72. 2). [144. myPolygonB.onPageLoad (the default).180]].animationSettings. myPolygonC. var myPolygonA = myPage.item(0).[108.animationSettings. 180]].[108. //Remove the default timing list.item(0).108].item("None")}). var myTimingGroupB = myTimingList. [72. [144.[[516.add({fillColor:myColorC.timingTargets.[[516. myPolygonA.duration = 2.animationSettings.[516.entirePath = [[72. myPolygonD.duration = 2. 180]. myTimingGroupB. //Create a motion path. myPolygonE. var myMotionPathPointsB = [[[[108.timingGroups..add(myPolygonD.duration = 2. 72].[516.timingTargets. myTimingGroupA.remove().animationSettings. var myPolygonC = myPage.[108. myPolygonA. 144]. var myTimingList = myTimingSettings.add(myPolygonC.motionPathPoints = myMotionPathPointsB. myPolygonD.

item(0). //Remove the default timing list in the timing settings for the spread. myTimingGroupB. //Add a page items to animate. myTimingGroup.timingGroups.timingGroups.timingSettings.add(myPolygonD.timingSettings. myPolygonA. myTimingGroupB. refer to PageItemTimingSettings). //Add a new timing list that triggers when the page is clicked. 2).CHAPTER 11: Creating Dynamic Documents Working with Animation 161 DynamicTriggerEvents. var myTimingGroup = myTimingList.timingGroups. 2). "myPolygonB". The animationSettings of the page item contain properties (such as rotationArray or hiddenAfter) that define the transformations that are applied during animation.timingLists. refer to MultipleTimingLists). we’ve worked with the timingSettings of the spread containing the page items we want to animate. myTimingListA. all of the polygons have already been added as timing targets //of the default timing list.item(-1).add(DynamicTriggerEvents.duration = 2.timingGroups. opacity.timingTargets.timingTargets. //Set animation preferences for the polygon.item(0). //Remove the last three timing groups in the timing list. //Given a document "myDocument" and a page "myPage" containg a polygon "myPolygonA". "myPolygonE".onPageLoad. var myTimingListA = myTimingSettings. myTimingGroup.animationSettings. Change the delay of myPolygonB and myPolygonC. The following script fragment shows how to make a page item rotate as it follows a motion path (for the complete script. rotation or skewing angles. Animating transformations Page items can change size.timingSettings.remove().. "myPolygonC".onPageClick).timingLists.remove(). 0). myTimingGroup = myTimingListA.animationSettings. var myTimingGroupB = myTimingListB.remove().timingTargets.delaySeconds = 2.add(myPolygonA. myTimingListA.onClick). var myTimingList = myTimingSettings.item(0). refer to AnimateRotation). by DynamicTriggerEvents.timingGroups. When you want to animate a page item when a user clicks the item.add(myPolygonF.delaySeconds = 2.item(0).timingGroups.item(2).parent. "myPolygonF".add(DynamicTriggerEvents.item(1). myPage. myTimingListA. var myTimingGroup = myTimingListA. In the previous examples.add(myPolygonE. "myPolygonD". . and visibility as their animation plays. //At this point. var myTimingListB = myTimingSettings. //Given a document "myDocument" and a page "myPage" containg 6 polygons: //"myPolygonA".parent. myPolygonA..motionPathPoints = myMotionPathPointsA.remove().timingTargets.onPageClick (for the complete script.item(-1).timingLists. as shown in the following script fragment (for the complete script.item(-1). you’ll need to use the timingSettings of the page item itself.timingGroups. 0).timingLists. var myTimingSettings = myPage. var myTimingSettings = myPolygonA.

[[516. myPolygonA. 108].. But InDesign can also use motion presets to define the animation of page items in a layout. var myTimingSettings = myPage.108].rotationArray = [[0. myTimingSettings.timingLists. and you can add new presets using either the user interface or scripting. var myMotionPathPoints = [[[[108. var myTimingGroup = myTimingList. refer to MotionPreset). the following line will //make the polygon rotate 360 degrees from the start to the end //of the animation.[108.motionPathPoints = myMotionPathPoints.timingLists. 108]]]. //Set animation preferences for the polygon.remove(). 95 = 4 seconds. //Add a page items to animate. For more on this topic. as seen in the following script fragment (for the complete script.playsLoop = true.108].animationSettings.add(DynamicTriggerEvents. 360]]. relative to the motion specified in the object’s animation settings. [144.timingSettings. for example. InDesign comes with a large number of motion presets. //Add a new timing list that triggers when the page is clicked.polygons.motionPresets..timingGroups. we’ve constructed motion paths and specified animation settings as if we were creating animations from the basic level in InDesign’s user interface.preset = myMotionPreset. 47 = 2 seconds. Motion presets In the preceding examples. 0).item("None")}).paths. 108].. //Assuming 24 Frames Per Second (FPS) //23 = 1 second. //Remove the default timing list. 72].item("move-right-grow"). 143 = 6 seconds //Since the duration of our animation is 2 seconds. A motion preset can apply a number of animation properties at once. A scripted animation can. apply transformations at each key frame of a given motion path. var myMotionPreset = app. myPolygonA. //Create a motion path.parent. myPolygonA. myOvalA.animationSettings.onPageClick). //Given a page containing the ovals "myOvalA".add({fillColor:myColorA. //Add the polygons to a single timing group.animationSettings.entirePath = [[72.true].duration = 2. The following script fragment shows how the design options for an animated shape can affect the playback of the animation (for the complete script. see “Key frames” later in this chapter.duration = 2.item(0). 119 = 5 seconds. refer to DesignOptions). Scripting offers more control over animation than can be achieved with InDesign’s user interface.. 0].[108. . 108]]. 71 = 3 seconds. strokeColor:myDocument.add(myPolygonA. Design options Design options affect the way that an animated object appears. 144]. [47.[516.[516.108]]. myOvalA. var myTimingList = myTimingSettings. [72. myPolygonA.animationSettings.animationSettings. var myPolygonA = myPage.CHAPTER 11: Creating Dynamic Documents Working with Animation 162 //Given a document "myDocument" and a page "myPage" and the color "myColorA".swatches.item(0).animationSettings. myOvalA.

. 100].animationSettings..animationSettings. [keyframe.animationSettings. which gives you the ability to apply changes to objects as they are animated. myOvalB.duration = 2. myOvalA. [23.animationSettings. scale].playsLoop = true.. myOvalA.200]. [47.opacityArray = [[0. [0.animationSettings.animationSettings.designOption = DesignOptions.[[468.preset = myMotionPreset. [47. [468. [47. myOvalC.. Key frames Key frames are points in the timeline of an animation.300]. myOvalB. [23. .item("move-right-grow"). 200].fromCurrentAppearance.animationSettings.animationSettings. 50]].0].animationSettings.motionPresets.animationSettings.." "myOvalB.] myOvalA. playing at 24 frames per second. [0. var myMotionPreset = app. 100]].0].scaleXArray = [[0. myOvalB. opacity]. [23. 60]].scaleYArray = [[0. myOvalC. myOvalA. [23. scale]. 100].] myOvalA.200]. you can add key frames at any time in the animation. 20].motionPath = myMotionPath.opacityArray = [[0.scaleXArray = [[0. and end //of a path.duration = 2. Key frames are part of the motion path applied to an animated page item.[[234.toCurrentAppearance.animationSettings. 400]]. [23.300].opacityArray = [[0. myOvalA.scaleYArray = [[0.designOption = DesignOptions. //The motion path is constructed relative to the center of the object. 100]]. the last frame in the animation is frame 48.duration = 2.animationSettings.animationSettings. midpoint.animationSettings. [keyframe.animationSettings. opacity]. [23...0].0]. myOvalB. myOvalB. [47.playsLoop = true. and how to change the transformations applied to an animated page item at each key frame.0]]]].playsLoop = true. [234.playsLoop = true.animationSettings. 80]].preset = myMotionPreset. myOvalB.animationSettings.playsLoop = true. //scaleXArray in the form [[keyframe. 100]. //scaleYArray in the form [[keyframe. //opacityArray in the form [[keyframe.scaleYArray = [[0. myOvalB.motionPath = myMotionPath.]. myOvalB. myOvalA. 40].animationSettings. 400]]. myOvalA..CHAPTER 11: Creating Dynamic Documents Working with Animation 163 //Given a page containing the ovals "myOvalA" and "myOvalB". [23. 10]. [47. myOvalB. [23. scale]. myOvalC. //The transformation changes at each key frame.scaleXArray = [[0.animationSettings.0]]]. myOvalA. var myMotionPath = [[0." and "myOvalC".. 50]]. [47. [keyframe. [468. [23.animationSettings.animationSettings.. . The following script fragment shows how to add key frames to a motion path. and key frames //are based on the duration of the animation divided by the number of frames per second //(usually 24).0]]].[[0. [47. For example. myOvalC. [47. myOvalB.. 100]].duration = 2.animationSettings.0].animationSettings.animationSettings. [234. [23. 50]. and are specified relative to the duration and speed of the animation.0]. refer to TransformAnimation. The following array sets key frames at the start.animationSettings.200]. 100]. 50]. [47.duration = 2. myOvalC.motionPath = myMotionPath. //Given a page containing ovals "myOvalA. myOvalC. scale]. 80]. myOvalA. [47. . For the complete script.animationSettings. for an animation with a duration of two seconds. With InDesign scripting.200]. 200].

spreads.medium. for(var myCounter = 0.length. refer to PageTransitions). and you'll see the page transitions. myCounter++){ myDocument. } //Export the document to SWF.pageTransitionType = PageTransitionTypeOptions..item(myCounter).spreads.pageTurnTransition. myCounter < myDocument.spreads. as shown in the following script fragment (for the complete script. .wipeTransition (for example).pageTransitionDuration = PageTransitionDurationOptions.spreads. //Given a document "myDocument" containing at least two spreads. Adding page transitions using scripting is easy. If you chose //PageTransitionTypeOptions. you would be //able to set those options.leftToRight. //This page transition option does not support the pageTransitionDirection //or pageTransitionDuration properties. //myDocument.CHAPTER 11: Creating Dynamic Documents Adding Page Transitions 164 Adding Page Transitions Page transitions are special effects that appear when you change pages in an exported dynamic document.item(myCounter). as shown in the next two lines: //myDocument.item(myCounter)..pageTransitionDirection = PageTransitionDirectionOptions.

The Best Approach to Scripting XML in InDesign You might want to do most of the work on an XML file outside InDesign. Any text that appears in a story associated with an XML element becomes part of that element’s data. see Chapter 13. XML uses angle brackets to indicate markup tags (for example. the best approach is to transform the XML using XSLT. The order in which XML elements appear in a layout largely depends on the order in which they appear in the XML structure. and XSLT.12 XML Extensible Markup Language. The InDesign representations of the XML elements are not the same thing as the XML elements themselves. or XML." 165 . XML allows you to describe content more precisely by creating custom tags. before you import the file into an InDesign layout. If the XML data is already formatted in an InDesign document. While HTML has a predefined set of tags. making XML work in a page-layout context is challenging. InDesign includes a complete set of features for importing XML data into page layouts. XML rules can search the XML structure in a document and process matching XML elements much faster than a script that does not use XML rules. you must duplicate the XML element itself. Overview Because XML is entirely concerned with content and explicitly not concerned with formatting. they become InDesign elements that correspond to the XML structure. “XML Rules. You can do this as you import the XML file. is a text-based mark-up system created and managed by the World Wide Web Consortium (www. If you want to duplicate the information of the XML element in the layout.w3. Working with XML outside InDesign. For more on working with XML rules. XML increasingly is used as a format for storing data. such as XML editors and parsers. you can use a wide variety of excellent tools. Each XML element can appear only once in a layout. InDesign’s approach to XML is quite complete and flexible. and these features can be controlled using scripting. When you need to rearrange or duplicate elements in a large XML data structure. DTDs. you probably will want to use XML rules if you are doing more than the simplest of operations.org). We also assume that you have some knowledge of XML. Like Hypertext Markup Language (HTML). We assume that you have already read Adobe InDesign CS5 Scripting Tutorial and know how to create and run a script. <article> or <para>). but it has a few limitations: Once XML elements are imported into an InDesign document. Because of its flexibility.

CHAPTER 12: XML

Scripting XML Elements

166

Scripting XML Elements
This section shows how to set XML preferences and XML import preferences, import XML, create XML elements, and add XML attributes. The scripts in this section demonstrate techniques for working with the XML content itself; for scripts that apply formatting to XML elements, see “Adding XML Elements to a Layout” on page 171.

Setting XML preferences
You can control the appearance of the InDesign structure panel using the XML view-preferences object, as shown in the following script fragment (from the XMLViewPreferences tutorial script):
var myDocument = app.documents.add(); var myXMLViewPreferences = myDocument.xmlViewPreferences; myXMLViewPreferences.showAttributes = true; myXMLViewPreferences.showStructure = true; myXMLViewPreferences.showTaggedFrames = true; myXMLViewPreferences.showTagMarkers = true; myXMLViewPreferences.showTextSnippets = true;

You also can specify XML tagging preset preferences (the default tag names and user-interface colors for tables and stories) using the XML preferences object., as shown in the following script fragment (from the XMLPreferences tutorial script):
var myDocument = app.documents.add(); var myXMLPreferences = myDocument.xmlPreferences; myXMLPreferences.defaultCellTagColor = UIColors.blue; myXMLPreferences.defaultCellTagName = "cell"; myXMLPreferences.defaultImageTagColor = UIColors.brickRed; myXMLPreferences.defaultImageTagName = "image"; myXMLPreferences.defaultStoryTagColor = UIColors.charcoal; myXMLPreferences.defaultStoryTagName = "text"; myXMLPreferences.defaultTableTagColor = UIColors.cuteTeal; myXMLPreferences.defaultTableTagName = "table";

Setting XML import preferences
Before importing an XML file, you can set XML import preferences that can apply an XSLT transform, govern the way white space in the XML file is handled, or create repeating text elements. You do this using the XML import-preferences object, as shown in the following script fragment (from the XMLImportPreferences tutorial script):

CHAPTER 12: XML

Scripting XML Elements

167

var myDocument = app.documents.add(); var myXMLImportPreferences = myDocument.xmlImportPreferences; myXMLImportPreferences.allowTransform = false; myXMLImportPreferences.createLinkToXML = false; myXMLImportPreferences.ignoreUnmatchedIncoming = true; myXMLImportPreferences.ignoreWhitespace = true; myXMLImportPreferences.importCALSTables = true; myXMLImportPreferences.importStyle = XMLImportStyles.mergeImport; myXMLImportPreferences.importTextIntoTables = false; myXMLImportPreferences.importToSelected = false; myXMLImportPreferences.removeUnmatchedExisting = false; myXMLImportPreferences.repeatTextElements = true; //The following properties are only used when the //AllowTransform property is set to True. //myXMLImportPreferences.transformFilename = "c:\myTransform.xsl" //If you have defined parameters in your XSL file, then you can pass //parameters to the file during the XML import process. For each parameter, //enter an array containing two strings. The first string is the name of the //parameter, the second is the value of the parameter. //myXMLImportPreferences.transformParameters = [["format", "1"]];

Importing XML
Once you set the XML import preferences the way you want them, you can import an XML file, as shown in the following script fragment (from the ImportXML tutorial script):
myDocument.importXML(File("/c/xml_test.xml"));

When you need to import the contents of an XML file into a specific XML element, use the importXML method of the XML element, rather than the corresponding method of the document. See the following script fragment (from the ImportXMLIntoElement tutorial script):
myXMLElement.importXML(File("/c/xml_test.xml"));

You also can set the importToSelected property of the xmlImportPreferences object to true, then select the XML element, and then import the XML file, as shown in the following script fragment (from the ImportXMLIntoSelectedElement tutorial script):
var myXMLTag = myDocument.xmlTags.add("xml_element"); var myXMLElement = myDocument.xmlElements.item(0).xmlElements.add(myXMLTag); myDocument.select(myXMLElement); myDocument.xmlImportPreferences.importToSelected = true; //Import into the selected XML element. myDocument.importXML(File("/c/xml_test.xml"));

Creating an XML tag
XML tags are the names of the XML elements you want to create in a document. When you import XML, the element names in the XML file are added to the list of XML tags in the document. You also can create XML tags directly, as shown in the following script fragment (from the MakeXMLTags tutorial script):
//You can create an XML tag without specifying a color for the tag. var myXMLTagA = myDocument.xmlTags.add("XML_tag_A"); //You can define the highlight color of the XML tag using the UIColors enumeration... var myXMLTagB = myDocument.xmlTags.add("XML_tag_B", UIColors.gray); //...or you can provide an RGB array to set the color of the tag. var myXMLTagC = myDocument.xmlTags.add("XML_tag_C", [0, 92, 128]);

CHAPTER 12: XML

Scripting XML Elements

168

Loading XML tags
You can import XML tags from an XML file without importing the XML contents of the file. You might want to do this to work out a tag-to-style or style-to-tag mapping before you import the XML data., as shown in the following script fragment (from the LoadXMLTags tutorial script):
myDocument.loadXMLTags(File("/c/test.xml"));

Saving XML tags
Just as you can load XML tags from a file, you can save XML tags to a file, as shown in the following script. When you do this, only the tags themselves are saved in the XML file; document data is not included. As you would expect, this process is much faster than exporting XML, and the resulting file is much smaller. The following sample script shows how to save XML tags (for the complete script, see SaveXMLTags):
myDocument.saveXMLTags(File("/c/xml_tags.xml"), "Tag set created October 5, 2006");

Creating an XML element
Ordinarily, you create XML elements by importing an XML file, but you also can create an XML element using InDesign scripting, as shown in the following script fragment (from the CreateXMLElement tutorial script):
var myDocument = myInDesign.documents.add(); var myXMLTagA = myDocument.xmlTags.add("XML_tag_A"); var myXMLElementA = myDocument.xmlElements.item(0).xmlElements.add(myXMLTagA); myXMLElementA.contents = "This is an XML element containing text.";

Moving an XML element
You can move XML elements within the XML structure using the move method, as shown in the following script fragment (from the MoveXMLElement tutorial script):
var myRootXMLElement = myDocument.xmlElements.item(0); var myXMLElementA = myRootXMLElement.xmlElements.item(0); myXMLElementA.move(LocationOptions.after, myRootXMLElement.xmlElements.item(2)); myRootXMLElement.xmlElements.item(-1).move(LocationOptions.atBeginning);

Deleting an XML element
Deleting an XML element removes it from both the layout and the XML structure, as shown in the following script fragment (from the DeleteXMLElement tutorial script).
myRootXMLElement.xmlElements.item(0).remove();

Duplicating an XML element
When you duplicate an XML element, the new XML element appears immediately after the original XML element in the XML structure, as shown in the following script fragment (from the DuplicateXMLElement tutorial script):

CHAPTER 12: XML

Scripting XML Elements

169

var myDocument = app.documents.item(0); var myRootXMLElement = myDocument.xmlElements.item(0); //Duplicate the XML element containing "A" var myNewXMLElement = myRootXMLElement.xmlElements.item(0).duplicate(); //Change the content of the duplicated XML element. myNewXMLElement.contents = myNewXMLElement.contents + " duplicate";

Removing items from the XML structure
To break the association between a page item or text and an XML element, use the untag method, as shown in the following script. The objects are not deleted, but they are no longer tied to an XML element (which is deleted). Any content of the deleted XML element becomes associated with the parent XML element. If the XML element is the root XML element, any layout objects (text or page items) associated with the XML element remain in the document. (For the complete script, see UntagElement.)
var myXMLElement = myDocument.xmlElements.item(0).xmlElements.item(0); myXMLElement.untag();

Creating an XML comment
XML comments are used to make notes in XML data structures. You can add an XML comment using something like the following script fragment (from the MakeXMLComment tutorial script):
var myRootXMLElement = myDocument.xmlElements.item(0); var myXMLElementB = myRootXMLElement.xmlElements.item(1); myXMLElementB.xmlComments.add("This is an XML comment.");

Creating an XML processing instruction
A processing instruction (PI) is an XML element that contains directions for the application reading the XML document. XML processing instructions are ignored by InDesign but can be inserted in an InDesign XML structure for export to other applications. An XML document can contain multiple processing instructions. An XML processing instruction has two parts, target and value. The following is an example:
<?xml-stylesheet type="text/css" href="generic.css"?>

The following script fragment shows how to add an XML processing instruction (for the complete script, see MakeProcessingInstruction):
var myRootXMLElement = myDocument.xmlElements.item(0); var myXMLProcessingInstruction = myRootXMLElement.xmlInstructions.add("xml-stylesheet type=\"text/css\" ", "href=\"generic.css\"");

Working with XML attributes
XML attributes are “metadata” that can be associated with an XML element. To add an XML attribute to an XML element, use something like the following script fragment (from the MakeXMLAttribute tutorial script). An XML element can have any number of XML attributes, but each attribute name must be unique within the element (that is, you cannot have two attributes named “id”).

By default. see XMLStory): var myXMLStory = myDocument. myRootXMLElement. myDocument.atEnd. the new XML element is created with the same XML tag as XML element containing the XML attribute. If you omit this parameter.atBeginning. The following script fragment shows how this works (for the complete script. You also can specify am XML mark-up tag for the new XML element. The following script fragment shows how to do this (for the complete script.documents.xmlAttributes. var myRootXMLElement = myDocument.xmlTags.xmlElements. Exporting XML To export XML from an InDesign document. you can convert XML elements to attributes.atEnd or LocationOptions.pages. It will not appear in the layout!").paragraphs. You also can convert an XML attribute to an XML element. When you do this. but cannot //be LocationOptions.pointSize = 72. Working with XML stories When you import XML elements that were not associated with a layout element (a story or page item). You can work with text in unplaced XML elements just as you would work with the text in a text frame. this method can fail when an attribute with that name already exists in the parent of the XML element. myDocument. those page items are deleted from the layout. the text contents of the XML element become the value of an XML attribute added to the parent of the XML element.item(-1).item(0). The new XML element can be added to the beginning or end of the parent of the XML attribute.xmlElements.xmlElements. When you convert an XML attribute to an XML element. all text //properties are available. export either the entire XML structure in the document or one XML element (including any child XML elements it contains).xmlAttributes.xmlElements.xmlElements.xmlElements. myXMLElementB.CHAPTER 12: XML Scripting XML Elements 170 var myDocument = app. myXMLElementB.item(0)).convertToElement(LocationOptions. //The "at" parameter can be either LocationOptions. see ConvertElementToAttribute): var myRootXMLElement = myDocument. The following script shows how to convert an XML element to an XML attribute (for the complete script.before. If the XML element contains page items. Because the name of the XML element becomes the name of the attribute.item(0). they are stored in an XML story. In addition to creating attributes directly using scripting.xmlElements.item("xml_element")).item(0). //Place the XML element in the layout to see the result. as shown in the following script fragment (from the ConvertAttributeToElement tutorial script): var myRootXMLElement = myDocument.item(1).item(0). see ExportXML): .after or LocationOptions.xmlElements.item(0). var myXMLElementB = myRootXMLElement.convertToAttribute(). the new element is added at the beginning of the parent element. var myXMLElementB = myRootXMLElement.placeXML(myDocument. myXMLStory. you can specify the location where the new XML element is added.item(0).item(0).xmlStories.item(1).item(0).item(0).add("example_attribute". //Though the text has not yet been placed in the layout. textFrames.item(0). "This is an XML attribute.

Associating XML elements with page items and text To associate a page item or text with an existing XML element. Adding XML Elements to a Layout Previously. To associate an XML element with an inline page item (i.item(0). myDocument. myXMLElement. This replaces the content of the page item with the content of the XML element. File("/c/partialDocumentXML. File("/c/selectedXMLElement. as shown in the following script fragment (from the PlaceIntoCopy tutorial script): . To associate an existing page item or text object with an existing XML element.CHAPTER 12: XML Adding XML Elements to a Layout 171 //Export the entire XML structure in the document. [72.exportFile(ExportFormat.item(0). myDocument. an anchored object).item(0). 288.item(0). File("/c/completeDocumentXML. we discuss techniques for getting XML information into a page layout and applying formatting to it.xmlElements.item(0)).pages.item(0)).xml. myDocument.points. you can use the exportFromSelected property of the xmlExportPreferences object to export an XML element selected in the user interface.xmlElements.item(0).select(myDocument.exportFile(ExportFormat. var myXMLElement = myDocument.horizontalMeasurementUnits = MeasurementUnits.viewPreferences.xmlElements.xmlElements. myDocument. see ExportSelectedXMLElement): myDocument.item(1)).viewPreferences.xmlElements. see PlaceIntoFrame): myDocument.xml")). 72. use the placeXML method.item(0).xmlExportPreferences.exportFromSelected = false. //Export the entire XML structure in the document. This merges the content of the page item or text with the content of the XML element (if any).. myDocument.item(0). myDocument.item(0).textFrames.pageOrigin. as shown in the following script fragment (for the complete script. //PlaceIntoFrame has two parameters: //On: The page. as shown in the following script fragment (from the PlaceXML tutorial script): myDocument.placeIntoFrame(myDocument.markup(myDocument.xml")).verticalMeasurementUnits = MeasurementUnits. With this method. use the markup method.viewPreferences. myDocument. The following script fragment shows how to use the markup method (for the complete script. spread. //Export a specific XML element and its child XML elements.pages.xml")).xml.xmlElements.pages.exportFile(ExportFormat.xmlExportPreferences.placeXML(myDocument.it em(0). 288]). or master spread on which to create the frame //GeometricBounds: The bounds of the new frame (in page coordinates).xmlElements.points.exportFromSelected = true.rulerOrigin = RulerOrigin. In this section.xml.item(0).item(-1).xmlElements. use the placeIntoCopy method. In addition.e.xmlElements. we covered the process of getting XML data into InDesign documents and working with the XML structure in a document. The following script fragment shows how to do this (for the complete script.te xtFrames. you can create a frame as you place the XML. see Markup): myDocument. Placing XML into page items Another way to associate an XML element with a page item is to use the placeIntoFrame method.

myXMLElement.pages.item(0).xmlElements.atBeginning).xmlElements.atEnd).placeIntoInlineFrame([72.xmlElements.placeIntoInlineCopy(myTextFrame. //Add static text outside the element.". myPage.item(1).item(0).xmlElements. //To insert text inside the text of an element.contents = "(the third word of) ". myXMLElement. not of the element itself.xmlElements. //To add text inside the element.item(0).after).add({geometricBounds:[72. myXMLElement. you can mark up existing page-layout content and add it to an XML structure. you often need to add white space (for example. LocationOptions. myXMLElement.textFrames. To associate an existing page item (or a copy of an existing page item) with an XML element and insert the page item into the XML structure at the location of the element. LocationOptions.item(0). myXMLElement. LocationOptions. myXMLElement.item(2).insertTextAsContent(" Text after the element.before). the character //becomes part of the content of the parent XML element.words. 72. 72]. var myXMLElement = myDocument. an XML publishing project does not start with an XML file—especially when you need to convert an existing page layout to XML.xmlElements.".item(3).pages. set the location option to beginning or end.after).insertionPoints.xmlElements. LocationOptions. as shown in the following script fragment (from the PlaceIntoInlineCopy tutorial script): var myPage = myDocument. LocationOptions. use the placeIntoInlineCopy method.xmlElements. false). LocationOptions. var myTextFrame = myDocument.before). myXMLElement.after). myXMLElement = myDocument. The following sample script shows how to add text in and around XML elements (for the complete script.item(0). LocationOptions.CHAPTER 12: XML Adding XML Elements to a Layout 172 var myPage = myDocument.item(2).insertTextAsContent("\r". see InsertTextAsContent): var myXMLElement = myDocument. You can then export this structure for further processing by XML tools outside InDesign.insertTextAsContent("Text at the start of the element: ". 96.xmlElements.item(0). var myXMLElement = myDocument. Inserting text in and around XML text elements When you place XML data into an InDesign layout. myXMLElement. myXMLElement.item(0). myXMLElement. To associate an XML element with a new inline frame.item(0). 24]). myXMLElement.insertTextAsContent("Text before the element: ".insertTextAsContent("Static text: ". .xmlElements.after).item(0).item(2). use the placeIntoInlineFrame method.item(0). Marking up existing layouts In some cases.xmlElements. as shown in the following script fragment (from the PlaceIntoInlineFrame tutorial script): var myXMLElement = myDocument.xmlElements.textFrames. LocationOptions. myXMLElement = myDocument.item(0).insertTextAsContent("\r". 144]}). return and tab characters) and static text (labels like “name” or “address”) to the text of your XML elements. For this type of project.insertTextAsContent(" Text at the end of the element.placeIntoCopy(myPage.item(0).item(2). //Specify width and height as you create the inline frame. myXMLElement.insertTextAsContent("\r". true). work with the text objects contained by the element.xmlElements. myXMLElement = myDocument. //By inserting the return character after the XML element. [288.

var myPage = myDocument. To do this. myDocument.textFrames.mapStylesToXMLTags().paragraphStyles.xmlTags.add(myDocument.xmlExportMaps.paragraphStyles.xmlTags.item(0). myDocument. When you do this.item(0).item("heading 2")). then use the mapStylesToXMLTags method to create the corresponding XML elements. which associates paragraph and character styles with XML tags.xmlTags.add(myDocument.pages.item("body_text").item("heading_1").item(0)). myStory. //Create a tag to style mapping.xmlExportMaps. var myTextFrame = myPage.xmlImportMaps. as shown in the following script fragment (from the MapTagsToStyles tutorial script): var myDocument = app. also known as tag-to-style mapping.paragraphStyles.item("heading_2")). myDocument.add(myDocument.xmlImportMaps.placeXML(myDocument.add(myDocument.paragraphStyles. //Place the XML element in the layout to see the result.xmlTags. Another approach is simply to have your script create a new XML tag for each paragraph or character style in the document. myDocument.add(myDocument.add(myDocument.xmlTags. use xmlExportMap objects to create the links between XML tags and styles.xmlExportMaps.item("para 1")).item("heading 1")).item("body text")).item("para_1")).xmlExportMaps. myDocument. When you use the mapXMLTagsToStyles method of the document. //Map the XML tags to the defined styles. and you want to move that text into an XML structure. InDesign applies the style to the text.xmlImportMaps.mapXMLTagsToStyles().xmlImportMaps.CHAPTER 12: XML Adding XML Elements to a Layout 173 Mapping tags to styles One of the quickest ways to apply formatting to XML text elements is to use XMLImportMaps. you can associate a specific XML tag with a paragraph or character style. myDocument.item("heading 1").parentStory. myDocument.add({geometricBounds:myGetBounds(myDocument. myPage)}).xmlElements. myDocument. var myStory = myTextFrame.documents. Mapping styles to tags When you have formatted text that is not associated with any XML elements.xmlTags.xmlTags.item("heading_2").item("body_text")). //Apply the style to tag mapping.add(myDocument.item("para_1").paragraphStyles. myDocument. myDocument.documents.paragraphStyles. and then apply the style to tag mapping.item(0). myDocument.item("para 1").item("heading 2"). //Create a style to tag mapping. as shown in the following script fragment (from the MapAllStylesToTags tutorial script): .paragraphStyles. as shown in the following script fragment (from the MapStylesToTags tutorial script): var myDocument = app.item("heading_1")). myDocument. myDocument. myDocument.item("body text").xmlTags.paragraphStyles. myDocument. myDocument. myDocument. use style-to-tag mapping.add(myDocument. myDocument.

"_") myXMLTagName = myXMLTagName. myHeading2Style.item(0).replace(/\ /gi.xmlElements.pointSize = 12.item(0).points.add("graphic"). myDocument.) var myDocument = app.documents.name. var myXMLElement = myDocument. } //Apply the style to tag mapping.name = "body text".paragraphStyles.pointSize = 12.add("body_text").viewPreferences. var myBodyTextXMLTag = myDocument.add("heading_2"). myBodyTextStyle. myHeading1Style. //Create a series of paragraph styles.add(myParagraphStyle.pointSize = 14.paragraphStyles. var myBodyTextStyle = myDocument.add().add(). var myXMLTagName = myParagraphStyleName. Applying styles to XML elements In addition to using tag-to-style and style-to-tag mappings or applying styles to the text and page items associated with XML elements.name = "heading 1". applyCharacterStyle.xmlElements.length.pages.mapStylesToXMLTags(). var myHeading2XMLTag = myDocument. .xmlTags.xmlTags. myPara1Style. myCounter<myDocument.paragraphStyles. myHeading2Style. //Create tags that match the style names in the document.spaceBefore = 12. myBodyTextStyle. "") myXMLTagName = myXMLTagName. see ApplyStylesToXMLElements. myCounter++){ var myParagraphStyle = myDocument.xmlExportMaps.xmlTags.firstLineIndent = 24. myDocument. myGraphic). myXMLTag). var myPara1XMLTag = myDocument. //Associate the graphic with a new XML element as you create the element.verticalMeasurementUnits = MeasurementUnits.add().xmlTags. myBodyTextStyle. myPara1Style. var myGraphic = myDocument. var myPara1Style = myDocument.replace(/\]/gi.documents.place(File(/c/test. myDocument. var myParagraphStyleName = myParagraphStyle. myHeading1Style. var myHeading1XMLTag = myDocument. var myHeading2Style = myDocument.horizontalMeasurementUnits = MeasurementUnits.replace(/\[/gi. see MarkingUpGraphics): var myXMLTag = myDocument. for(var myCounter = 0. The following script fragment shows how to use three methods: applyParagraphStyle.add(myXMLTagName).Item(0).add(myXMLTag. myDocument.paragraphStyles. myHeading2Style. //Create a series of XML tags.name = "para 1". var myHeading1Style = myDocument. (For the complete script. you also can apply styles to XML elements directly.pointSize = 24.points.CHAPTER 12: XML Adding XML Elements to a Layout 174 var myDocument = app.add().firstLineIndent = 0.item(myCounter).xmlTags. "") var myXMLTag = myDocument.add("para_1").paragraphStyles.name = "heading 2". //creating an XMLExportMap for each tag/style pair.add(). and applyObjectStyle.viewPreferences. myPara1Style. Marking up graphics The following script fragment shows how to associate an XML element with a graphic (for the complete script.xmlTags.paragraphStyles.add("heading_1").tif")).

add(myPara1XMLTag). true).contents = "Note:". To use this method. true). myStory. myXMLElementF.xmlElements. XMLElementPosition. myXMLElementB.add(myBodyTextXMLTag).afterElement). XMLElementPosition. myXMLElementD.insertTextAsContent("\r".xmlElements. myXMLElementB. myXMLElementA. var myXMLElementD = myRootXMLElement.afterElement). The following script fragment shows how to use this method (for the complete script. myXMLElementF) myXMLElementG. myXMLElementG.name = "Emphasis".applyParagraphStyle(myPara1Style. var myXMLElementC = myRootXMLElement.add(). Each row of the table must correspond to a specific XML element.add(myBodyTextXMLTag).add(myPara1XMLTag).characterStyles. myXMLElementC.applyParagraphStyle(myBodyTextStyle.".applyParagraphStyle(myHeading2Style. myXMLElementG = myXMLElementG.insertTextAsContent(" ". var myXMLElementB = myRootXMLElement.atBeginning. myXMLElementF. myXMLElementE.CHAPTER 12: XML Adding XML Elements to a Layout 175 //Create a character style.".applyParagraphStyle(myPara1Style. see ConvertXMLElementToTable).xmlElements.insertTextAsContent("\r".". Working with XML tables InDesign automatically imports XML data into table cells when the data is marked up using HTML standard table tags. myXMLElementF. myXMLElementC.add({geometricBounds:myGetBounds(myDocument. myXMLElementE. true). myCharacterStyle. myPage)}).xmlElements. myXMLElementC. myXMLElementE. myXMLElementG.xmlElements. XMLElementPosition. var myXMLElementF = myRootXMLElement. myXMLElementD.item(0).add(myHeading2XMLTag). XMLElementPosition. and that element must contain a series of XML elements corresponding to the cells in the row.contents = "This is the first paragraph in the article.contents = "Heading 1". myXMLElementA. var myStory = myTextFrame.move(LocationOptions. var myCharacterStyle = myDocument.xmlElements. //Add XML elements and apply paragraph styles. InDesign can convert XML elements to a table using the convertElementToTable method. the XML elements to be converted to a table must conform to a specific structure.afterElement). true). var myXMLElementG = myRootXMLElement.afterElement). If you cannot use the default table mark-up or prefer not to use it.pages. XMLElementPosition. var myXMLElementA = myRootXMLElement.insertTextAsContent("\r".".afterElement).textFrames.insertTextAsContent("\r". XMLElementPosition.afterElement).item(0). myXMLElementD. XMLElementPosition.insertTextAsContent("\r".xmlElements.contents = "Heading 2". The XML element used to denote the table row is consumed by this process. true).contents = "This is the second paragraph following the subhead. var myXMLElementE = myRootXMLElement. myCharacterStyle.applyParagraphStyle(myBodyTextStyle. . myXMLElementA.fontStyle = "Italic".contents = "This is the second paragraph in the article.applyParagraphStyle(myHeading1Style.xmlElements. var myRootXMLElement = myDocument.add(myBodyTextXMLTag). // Add text elements.placeXML(myRootXMLElement). var myTextFrame = myPage.afterElement).insertTextAsContent("\r".parentStory.contents = "This is the first paragraph following the subhead. true). true).applyCharacterStyle(myCharacterStyle.add(myHeading1XMLTag). var myPage = myDocument. myXMLElementB.

CHAPTER 12: XML

Adding XML Elements to a Layout

176

var myDocument = app.documents.add(); //Create a series of XML tags. var myRowTag = myDocument.xmlTags.add("row"); var myCellTag = myDocument.xmlTags.add("cell"); var myTableTag = myDocument.xmlTags.add("table"); //Add XML elements. var myRootXMLElement = myDocument.xmlElements.item(0); with(myRootXMLElement){ var myTableXMLElement = xmlElements.add(myTableTag); with(myTableXMLElement){ for(var myRowCounter = 1;myRowCounter < 7;myRowCounter++){ with(xmlElements.add(myRowTag)){ myString = "Row " + myRowCounter; for(var myCellCounter = 1; myCellCounter < 5; myCellCounter++){ with(xmlElements.add(myCellTag)){ contents = myString + ":Cell " + myCellCounter; } } } } } } var myTable = myTableXMLElement.convertElementToTable(myRowTag, myCellTag); // Add text elements. var myPage = myDocument.pages.item(0); var myTextFrame = myPage.textFrames.add({geometricBounds:myGetBounds(myDocument, myPage)}); var myStory = myTextFrame.parentStory; myStory.placeXML(myRootXMLElement);

Once you are working with a table containing XML elements, you can apply table styles and cell styles to the XML elements directly, rather than having to apply the styles to the tables or cells associated with the XML elements. To do this, use the applyTableStyle and applyCellStyle methods, as shown in the following script fragment (from the ApplyTableStyles tutorial script):
var myDocument = app.documents.add(); //Create a series of XML tags. var myRowTag = myDocument.xmlTags.add("row"); var myCellTag = myDocument.xmlTags.add("cell"); var myTableTag = myDocument.xmlTags.add("table"); //Create a table style and a cell style. var myTableStyle = myDocument.tableStyles.add({name:"myTableStyle"}); myTableStyle.startRowFillColor = myDocument.colors.item("Black"); myTableStyle.startRowFillTint = 25; myTableStyle.endRowFillColor = myDocument.colors.item("Black"); myTableStyle.endRowFillTint = 10; var myCellStyle = myDocument.cellStyles.add(); myCellStyle.fillColor = myDocument.colors.item("Black"); myCellStyle.fillTint = 45 //Add XML elements. var myRootXMLElement = myDocument.xmlElements.item(0); with(myRootXMLElement){ var myTableXMLElement = xmlElements.add(myTableTag); with(myTableXMLElement){ for(var myRowCounter = 1;myRowCounter < 7;myRowCounter++){ with(xmlElements.add(myRowTag)){ myString = "Row " + myRowCounter; for(var myCellCounter = 1; myCellCounter < 5; myCellCounter++){ with(xmlElements.add(myCellTag)){ contents = myString + ":Cell " + myCellCounter;

CHAPTER 12: XML

Adding XML Elements to a Layout

177

} } } } } } var myTable = myTableXMLElement.convertElementToTable(myRowTag, myCellTag); var myTableXMLElement = myDocument.xmlElements.item(0).xmlElements.item(0); myTableXMLElement.applyTableStyle(myTableStyle); myTableXMLElement.xmlElements.item(0).applyCellStyle(myCellStyle); myTableXMLElement.xmlElements.item(5).applyCellStyle(myCellStyle); myTableXMLElement.xmlElements.item(10).applyCellStyle(myCellStyle); myTableXMLElement.xmlElements.item(15).applyCellStyle(myCellStyle); myTableXMLElement.xmlElements.item(16).applyCellStyle(myCellStyle); myTableXMLElement.xmlElements.item(21).applyCellStyle(myCellStyle); // Add text elements. var myPage = myDocument.pages.item(0); var myTextFrame = myPage.textFrames.add({geometricBounds:myGetBounds(myDocument, myPage)}); var myStory = myTextFrame.parentStory; myStory.placeXML(myRootXMLElement); myTable.alternatingFills = AlternatingFillsTypes.alternatingRows;

13

XML Rules
The InDesign XML- rules feature provides a powerful set of scripting tools for working with the XML content of your documents. XML rules also greatly simplify the process of writing scripts to work with XML elements and dramatically improve performance of finding, changing, and formatting XML elements. While XML rules can be triggered by application events, like open, place, and close, typically you will run XML rules after importing XML into a document. (For more information on attaching scripts to events, see Chapter 8, “Events.”) This chapter gives an overview of the structure and operation of XML rules, and shows how to do the following: Define an XML rule. Apply XML rules. Find XML elements using XML rules. Format XML data using XML rules. Create page items based on XML rules. Restructure data using XML rules. Use the XML-rules processor. We assume that you have already read Adobe InDesign CS5 Scripting Tutorial and know how to create and run a script. We also assume that you have some knowledge of XML and have read Chapter 12, “XML.”

Overview
InDesign’s XML rules feature has three parts: XML rules processor (a scripting object) — Locates XML elements in an XML structure using XPath and applies the appropriate XML rule(s). It is important to note that a script can contain multiple XML rule processor objects, and each rule-processor object is associated with a given XML rule set. Glue code — A set of routines provided by Adobe to make the process of writing XML rules and interacting with the XML rules-processor easier. XML rules — The XML actions you add to a script. XML rules are written in scripting code. A rule combines an XPath-based condition and a function to apply when the condition is met. The “apply” function can perform any set of operations that can be defined in InDesign scripting, including changing the XML structure; applying formatting; and creating new pages, page items, or documents. A script can define any number of rules and apply them to the entire XML structure of an InDesign document or any subset of elements within the XML structure. When an XML rule is triggered by an XML rule processor, the rule can apply changes to the matching XML element or any other object in the document. You can think of the XML rules feature as being something like XSLT. Just as XSLT uses XPath to locate XML elements in an XML structure, then transforms the XML elements in some way, XML rules use XPath to
178

CHAPTER 13: XML Rules

Overview

179

locate and act on XML elements inside InDesign. Just as an XSLT template uses an XML parser outside InDesign to apply transformations to XML data, InDesign's XML Rules Processor uses XML rules to apply transformations to XML data inside InDesign.

Why use XML rules?
In prior releases of InDesign, you could not use XPath to navigate the XML structure in your InDesign files. Instead, you needed to write recursive script functions to iterate through the XML structure, examining each element in turn. This was difficult and slow. XML rules makes it easy to find XML elements in the structure, by using XPath and relying on InDesign's XML-rules processors to find XML elements. An XML-rule processor handles the work of iterating through the XML elements in your document, and it can do so much faster than a script.

XML-rules programming model
An XML rule contains three things: 1. A name (as a string). 2. An XPath statement (as a string). 3. An apply function. The XPath statement defines the location in the XML structure; when the XML rules processor finds a matching element, it executes the apply function defined in the rule. Here is a sample XML rule:
function RuleName() { this.name = "RuleNameAsString"; this.xpath = "ValidXPathSpecifier"; this.apply = function (element, ruleSet, ruleProcessor){ //Do something here. //Return true to stop further processing of the XML element return true; }; // end of Apply function }

In the above example, RuleNameAsString is the name of the rule and matches the RuleName; ValidXPathSpecifier is an XPath expression. Later in this chapter, we present a series of functioning XML-rule examples. NOTE: XML rules support a limited subset of XPath 1.0. See “XPath limitations” on page 183.”

XML-rule sets
An XML-rule set is an array of one or more XML rules to be applied by an XML-rules processor. The rules are applied in the order in which they appear in the array. Here is a sample XML-rule set:
var myRuleSet = new Array (new SortByName, new AddStaticText, new LayoutElements, new FormatElements );

__processChildren(ruleProcessor) — This function directs the XML-rules processor to apply matching XML rules to child elements of the matched XML element. These functions are defined within the glue code.xml file into a new document. The XML element defines the point in the XML structure at which to begin processing the rules. To see how all these functions work together. the XML-rules processor continues searching for rules to apply to the descendents of that XML element. You can use this script in conjunction with the AddAttribute tutorial script to troubleshoot XML traversal problems in your own XML documents (you must edit the AddAttribute script to suit your XML structure). An XML rule can alter this behavior by using the __skipChildren or __processChildren function. By default. For each “branch” of the XML structure. we present several functioning scripts containing XML-rule sets. __skipChildren(ruleProcessor) — This function tells the processor not to process any descendants of the current XML element using the XML rule. just like the normal ordering of nested tags in an XML file). Adobe provides a set of functions intended to make the process of writing XML rules much easier. Use this function when you want to move or delete the current XML element or improve performance by skipping irrelevant parts of an XML structure. the XML-rules processor tries to apply all matching XML rules in the order in which they are added to the current XML rule set. You can use the __processChildren function to return control to the apply function of the rule after the child XML elements are processed. import the DepthFirstProcessingOrder.jsx file: __processRuleSet(root. This allows the rule applied to a parent XML element to execute code after the child XML elements are processed.jsx script. ruleSet) — To execute a set of XML rules. After an XML rule is applied to an XML element. when an XML-rules processor applies a rule to the children of an XML element. “Glue” code In addition to the XML-rules processor object built into InDesign’s scripting model. that is.CHAPTER 13: XML Rules Overview 180 In the above example. and it visits each XML element in the structure twice (in the order parent-child-parent. The __processRuleSet function applies rules to XML elements in “depth first” order. InDesign creates a text frame. Normal iteration (assuming a rule that matches every XML element in the structure) is shown in the following figure: . that lists the attribute names of each element in the sample XML file in the order in which they were visited by each rule. the rules listed in the myRuleSet array are defined elsewhere in the script. then run the DepthFirstProcessingOrder. control does not return to the rule. or by changing the operation of other rules. The XML-rules processor uses a forward-only traversal of the XML structure. the XML-rules processor visits each XML element before moving on to the next branch. For any XML element. XML elements and their child elements are processed in the order in which they appear in the XML structure. Later in this chapter. Iterating through an XML structure The XML-rules processor iterates through the XML structure of a document by processing each XML element in the order in which it appears in the XML hierarchy of the document. your script must call the __processRuleSet function and provide an XML element and an XML rule set.

see ProcessChildren.) . (For the complete script.CHAPTER 13: XML Rules Overview 181 Root 1 B 2 9 BA 3 4 5 BB BC 8 BAA BAB 6 7 BACA BACB BAC Iteration with __processChildren (assuming a rule that matches every XML element in the structure) is shown in the following figure: Root 9 B 8 6 7 BA 5 4 3 BB BC BAA BAB BAC 2 1 BACA BACB Iteration given the following rule set is shown in the figure after the script fragment. including one that uses __processChildren. The rule set includes two rules that match every element. Every element is processed twice.

return false. To prevent errors that might cause the XML-rules processor to become invalid.contents = myElement. create a separate rule that matches and processes the ancestor XML element.insertionPoints. //XPath will match on every part_number XML element in the XML structure.apply = function(myElement.stories.documents.xmlAttributes. return false.item(0).CHAPTER 13: XML Rules Overview 182 function NormalRule(){ this. //XPath will match on every part_number XML element in the XML structure. the rule can change the XML structure of the document.name = "NormalRule".xpath = "//XMLElement". app. myRuleProcessor){ app.item(-1). . // Define the apply function. This can conflict with the process of applying other rules.apply = function(myElement.item(-1). // Define the apply function. this.item(0).xpath = "//XMLElement". the following limitations are placed on XML structure changes you might make within an XML rule: Deleting an ancestor XML element — To delete an ancestor XML element of the matched XML element.contents = myElement.stories. } //End of apply function } Root 1 19 2 14 B 18 16 BA 3 5 7 13 BB 15 BC 17 BAA 4 BAB 6 8 BAC 12 10 BACA 9 BACB 11 Changing structure during iteration When an XML-rules processor finds a matching XML element and applies an XML rule. myRuleProcessor){ __processChildren(myRuleProcessor).name = "ProcessChildrenRule". this. this.item(0).xmlAttributes. } //End of apply function } function ProcessChildrenRule(){ this.item(0).insertionPoints.documents.item(0). this.item(0). if the affected XML elements in the structure are part of the current path of the XML-rules processor.value + "\r".value + "\r".

/doc/comment(). use the __skipChildren function before making the change. /doc/note/following-sibling::*. Find an element with a specified attribute that matches a specified value. XPath limitations InDesign’s XML rules support a limited subset of the XPath 1. including . /doc/para[@font='Courier'][@size=5][2]. for example.CHAPTER 13: XML Rules Overview 183 Inserting a parent XML element — To add an ancestor XML element to the matched XML element. do so after processing the current XML element. for example. Find comment as a terminal. for example. /doc/title. /doc/para[@font !='Courier']. Find PI by target or any. for example. Find self or any descendent. preceding-sibling::.0 specification. up to the point that one of the rule apply functions returns true. Handling multiple matching rules When multiple rules match an XML element. the following XPath expressions are specifically excluded: No ancestor or preceding-sibling axes. //para. like the state of another variable in the script. returning true means the element was processed. Find multiple predicates. . Due to the one-pass nature of this implementation. specifically including the following capabilities: Find an element by name. Find a child element by numeric position (but not last()). XML rules are applied in the order in which they appear in the rule set. for example. /doc/para[3]. specifying a path from the root. any other XML rules matching the XML element are ignored. The ancestor XML element you add is not processed by the XML-rules processor during this rule iteration (as it appears “above” the current element in the hierarchy). you can control the matching behavior of the XML rule based on a condition other than the XPath property defined in the XML rule. for example. for example. /doc/processing-instruction('foo'). To make this sort of change... for example. the XML-rules processor can apply some or all of the matching rules. Find paths with wildcards and node matches. You can alter this behavior and allow the next matching rule to be applied. for example. Find along following-sibling axes. In essence. ancestor::. No repetitive processing — Changes to nodes that were already processed will not cause the XML rule to be evaluated again. /doc/para[@font='Courier']. for example. by having the XML rule apply function return false. Find an element with a specified attribute that does not match a specified value. Deleting the current XML element — You cannot delete or move the matched XML element until any child XML elements contained by the element are processed. Once a rule returns true. When an apply function returns false. /doc/*/subtree/node().

catch blocks. InDesign does include a series of errors specific to XML-rules processing. foo[@bar < font or @c > 3]. Results and errors are passed back up the chain until they are handled by a function or cause a scripting error. however. When InDesign generates an error. XML rules flow of control As a script containing XML rules executes. The error message indicates which XML structural change caused the error. an XML-rules script behaves no differently than any other script. No compound Boolean predicates. No text() function or text comparisons. foo[@bar=font or @c=size].CHAPTER 13: XML Rules Overview 184 No path specifications in predicates. XML structure changes caused by the operation of XML rules can invalidate the XML-rules processor. doc/chapter. scripts that use rules do not differ in nature from ordinary scripts.. or a user action initiated from the user interface. for example. No relative paths. The following diagram provides a simplified overview of the flow of control in an XML-rules script: . An InDesign error also can be caused by a model change that invalidates the state of an XML-rules processor. iterates through the XML elements in the structure. another concurrently executing script. XML structure changes that invalidate an XML-rules processor lead to errors when the XML-rules processor's iteration resumes. for example. the flow of control passes from the script function containing the XML rules to each XML rule. Those functions pass control to the XML-rules processor which. foo[bar/c].. for example. in turn. try. No last() function. These changes to the XML structure can be caused by the script containing the XML-rules processor. for example. you can use InDesign scripting to examine the text content of an XML element matched by a given XML rule. An InDesign error can occur at XML-rules processor initialization. for example. Error handling Because XML rules are part of the InDesign scripting model. No relational predicates. when a rule uses a non-conforming XPath specifier (see “XPath limitations” on page 183). and they benefit from the same error-handling mechanism. InDesign errors can be captured in the script using whatever tools the scripting language provides to achieve that. and from each rule to the functions defined in the glue code.

we present a series of XML-rules exercises based on a sample XML data file. run the following script before you run each sample XML-rule script (see the XMLRulesExampleSetup. This means it is almost impossible to demonstrate a functional XML-rules script without having an XML structure to test it against. then choose File > Revert before running each sample script in this section.jsx script file): . Setting up a sample document Before you run each script in this chapter. Save the file. In the remainder of this chapter.CHAPTER 13: XML Rules XML Rules Examples 185 XML rules script XM Lr ule s glue code XML rule processor XML rule XPath condition XPath condition __processRuleSet t XML elemen XML element XPath evaluation apply() __processChildren t XML elemen XML structure iteration __skipChildren XML Rules Examples Because XML rules rely on XPath statements to find qualifying XML elements. Alternately. Each record in the XML data file has the following structure: <device> <name></name> <type></type> <part_number></part_number> <supply_voltage> <minimum></minimum> <maximum></maximum> </supply_voltage> <package> <type></type> <pins></pins> </package> <price></price> <description></description> </device> The scripts are presented in order of complexity. For our example. turn on the Do Not Import Contents of Whitespace-Only Elements option in the XML Import Options dialog box. import the XMLRulesExampleData. we use the product list of an imaginary integrated-circuit manufacturer. XML rules are closely tied to the structure of the XML in a document.xml data file into a document. When you import the XML. starting with a very simple script and building toward more complex operations.

left.myPage.activeScript. myY2.xmlImportPreferences.pages.marginPreferences. var myX2 = myWidth . . myDocument.xmlImportPreferences.xml" myDocument. myDocument.documents. } } } Getting started with XML rules Here is a very simple XML rule—it does nothing more than add a return character after every XML element in the document. function main(){ var myDocument = app. myPage){ var myWidth = myDocument.marginPreferences.myPage.right.placeIntoFrame(myDocument.path + "/XMLRulesExampleData.marginPreferences. } catch(myError){ return File(myError. var myBounds = myGetBounds(myDocument. var myHeight = myDocument. var myFilePath = myScriptPath.CHAPTER 13: XML Rules XML Rules Examples 186 //XMLRuleExampleSetup. myBounds).item(0)). myDocument. myDocument.jsx // main().documentPreferences. var myScriptPath = myGetScriptPath(). var myY2 = myHeight . function myGetBounds(myDocument. myX1.importXML(File(myFilePath)).pageWidth. return [myY1.item(0). } function myGetScriptPath() { try { return app. myX2].marginPreferences.item(0).pages. For the complete script.allowTransform = false.fileName).documentPreferences.bottom.top. var myY1 = myPage.add().xmlElements.pageHeight. see AddReturns. The XML-rule set contains one rule.ignoreWhitespace = true. var myX1 = myPage.

new ProcessPrice). function main(){ if (app. } //Adds a return character at the end of every XML element.documents. XMLElementPosition. main().name = "AddReturns". this. new ProcessPackageType. new ProcessSupplyVoltage.CHAPTER 13: XML Rules XML Rules Examples 187 main(). function AddReturns(){ this. new ProcessType.item(0). It is somewhat more complex. function main(){ if (app. } } else{ alert("No open document"). new ProcessName. __processRuleSet(elements. For the complete script. new ProcessPackages. //XPath will match on every XML element in the XML structure. var myRuleSet = new Array (new AddReturns). //This rule set contains a single rule. myRuleProcessor){ with(myElement){ //Add a return character at the end of the XML element. new ProcessPartNumber. myRuleSet). however.// Succeeded } //End of apply function } } Adding white space and static text The following XML rule script is similar to the previous script. myRuleSet). insertTextAsContent("\r".length != 0){ var myDocument = app.item(0).xpath = "//*".documents.item(0).item(0). this.apply = function(myElement.documents. var myRuleSet = new Array (new ProcessDevice. } } else{ alert("No open document"). } return true. with(myDocument){ var elements = xmlElements.length != 0){ var myDocument = app. } //Adds a return character at the end of the "device" XML element. __processRuleSet(elements. . //This rule set contains a single rule.documents.ELEMENT_END). in that it treats some XML elements differently based on their element names. in that it adds white space and static text. see AddReturnsAndStaticText. new ProcessPackageOne. // Define the apply function. with(myDocument){ var elements = xmlElements.

// Succeeded } //End of apply function } //Adds a return character at the end of the "name" XML element.beforeElement). this.afterElement). insertTextAsContent("\r". function ProcessType(){ this. this.// Succeeded } //End of apply function } //Adds a return character at the end of the "type" XML element. this.CHAPTER 13: XML Rules XML Rules Examples 188 function ProcessDevice(){ this.xpath = "/devices/device". } return true.afterElement). insertTextAsContent("Circuit Type: ".xpath = "/devices/device/type". XMLElementPosition. XMLElementPosition. function ProcessName(){ this. // Define the apply function.name = "ProcessType".afterElement).beforeElement). this.name = "ProcessDevice". } return true. //Add a return character at the end of the XML element. myRuleProcessor){ with(myElement){ //Add static text at the beginning of the XML element. this. myRuleProcessor){ with(myElement){ //Add static text at the beginning of the XML element. XMLElementPosition. insertTextAsContent("\r". this. myRuleProcessor){ with(myElement){ //Add a return character at the end of the XML element.apply = function(myElement.xpath = "/devices/device/name". this. XMLElementPosition. insertTextAsContent("\r". insertTextAsContent("Device Name: ".apply = function(myElement. //Add a return character at the end of the XML element.beforeElement).// Succeeded } //End of apply function } . insertTextAsContent("Part Number: ". XMLElementPosition. // Define the apply function. //Add a return character at the end of the XML element.apply = function(myElement. this.name = "ProcessPartNumber". myRuleProcessor){ with(myElement){ //Add static text at the beginning of the XML element. function ProcessPartNumber(){ this. } return true. insertTextAsContent("\r".name = "ProcessName".xpath = "/devices/device/part_number". // Define the apply function. // Define the apply function.apply = function(myElement. XMLElementPosition.beforeElement).// Succeeded } //End of apply function } //Adds a return character at the end of the "part_number" XML element. } return true. XMLElementPosition.

this.afterElement). this. // Define the apply function.xmlElements. XMLElementPosition. } with(myElement. } //End of apply function } //Add the text "Package:" before the list of packages. this. } //End of apply function } //Add commas between the package types. } return true.name = "ProcessPackageOne". function ProcessSupplyVoltage(){ this.afterElement).elementEnd). this. XMLElementPosition.xmlElements. XMLElementPosition. insertTextAsContent("Supply Voltage: From ".name = "ProcessSupplyVoltage".name == "package"){ insertTextAsContent(".apply = function(myElement. this. . //Return false to let other XML rules process the element.afterElement).name = "ProcessPackageType".apply = function(myElement.parent. this.markupTag.item(-1)){ //Add static text to the beginning of the voltage range. } return false. myRuleProcessor){ with(myElement){ insertTextAsContent("Package: ". XMLElementPosition.name = "ProcessPackages". XMLElementPosition. this. If we use XMLElementPosition. myRuleProcessor){ //Note the positions at which we insert the static text.CHAPTER 13: XML Rules XML Rules Examples 189 //Adds static text around the "minimum" and "maximum" //XML elements of the "supply_voltage" XML element.xpath = "/devices/device/package". XMLElementPosition. myRuleProcessor){ with(myElement){ if(myElement.xpath = "/devices/device/supply_voltage". the static text will appear //inside the XML element. function ProcessPackageOne(){ this.nextItem(myElement).apply = function(myElement. // Define the apply function.elementStart).apply = function(myElement. } //Add a return at the end of the XML element. with(myElement. with(myElement){ //Add static text to the beginning of the voltage range.item(0)){ insertTextAsContent(" to ".xpath = "/devices/device/package[1]". function ProcessPackages(){ this.xmlElements. this. } return true. insertTextAsContent(" volts".afterElement. myRuleProcessor){ with(myElement){ insertTextAsContent("-".elementEnd.// Succeeded } //End of apply function } function ProcessPackageType(){ this. If we use //XMLElementPosition. XMLElementPosition. //the static text appears outside the XML elment (as a text element of //the parent element).xpath = "/devices/device/package/type".afterElement). ".elementStart). insertTextAsContent("\r".

apply = function(myElement. XMLElementPosition. } } Changing the XML structure using XML rules Because the order of XML elements is significant in InDesign’s XML implementation. //Match all following sibling XML elements //of the first "item" XML element.afterElement). ". //Let other XML rules process the element.CHAPTER 13: XML Rules XML Rules Examples 190 } else{ insertTextAsContent("\r". } } return true. this.name = "ProcessPrice". __processRuleSet(elements. this. Given the following example XML structure: <xmlElement><item>1</item><item>2</item><item>3</item><item>4</item> </xmlElement> To add commas between each item XML element in a layout. XMLElementPosition.item(0). you could use an XML rule like the following (from the ListProcessing tutorial script): var myRuleSet = new Array (new ListItems). } return false. XMLElementPosition. If you have a sequence of similar elements at the same level. } return true.beforeElement).// Succeeded } //End of apply function } } NOTE: The above script uses scripting logic to add commas between repeating elements (in the ProcessPackages XML rule). you might need to use XML rules to change the sequence of elements in the structure. var myDocument = app. In general.name = "ListItems". function ListItems(){ this. } //Add commas between each "item" element.apply = function(myElement. you can use forward-axis matching to do the same thing. with(myDocument){ var elements = xmlElements. // Define the apply function. large-scale changes to the . myRuleSet). //Add a return at the end of the XML element.item(0). XMLElementPosition.beforeElement). insertTextAsContent("\r".documents. myRuleProcessor){ with(myElement){ insertTextAsContent("Price: $". this. this. myRuleProcessor){ with(myElement){ insertTextAsContent(".xpath = "/xmlElement/item[1]/following-sibling::*".afterElement). } //End of apply function } function ProcessPrice(){ this.xpath = "/devices/device/price".

myRuleSet). myElement. Note the use of the __skipChildren function from the glue code to prevent the XML-rules processor from becoming invalid. If you want the content of an XML element to appear more than once in a layout. Again.length != 0){ var myDocument = app. myRuleProcessor){ //Moves the part_number XML element to the start of //the device XML element (the parent).item(0).xmlElements.before.” XML elements have a one-to-one relationship with their expression in a layout.documents. For the complete script.xpath = "/devices/device/part_number". main(). The following script shows how to duplicate elements using XML rules. __skipChildren(myRuleProcessor). The following XML rule script shows how to use the move method to accomplish this.CHAPTER 13: XML Rules XML Rules Examples 191 structure of an XML document are best done using an XSLT file to transform the document before or during XML import into InDesign. this. with(myDocument){ var elements = xmlElements.name = "MoveElement". //This rule set contains a single rule. function main(){ if (app. __processRuleSet(elements. function MoveElement(){ this.documents.apply = function(myElement. For the complete script. you need to duplicate the element. } } else{ alert("No open document").item(0)).move(LocationOptions. //XPath will match on every part_number XML element in the XML structure. see MoveXMLElement. return true.item(0).parent. see DuplicateXMLElement. this. // Define the apply function. myElement.// Succeeded } //End of apply function } } Duplicating XML elements with XML rules As discussed in Chapter 12. var myRuleSet = new Array (new MoveElement). . this rule uses __skipChildren to avoid invalid XML object references. } //Adds a return character at the end of every XML element. “XML.

this.jsx" main(). When you need to find an element by its text contents. } //Duplicates the part number element in each XML element.duplicate(). myRuleSet).documents.CHAPTER 13: XML Rules XML Rules Examples 192 #include "glue code. } } else{ alert("No open document").item(0). myElement.documents.xpath = "/devices/device/part_number". var myRuleSet = new Array (new DuplicateElement). function main(){ if (app. see AddAttribute. } } } XML rules and XML attributes The following XML rule adds attributes to XML elements based on the content of their “name” element. __skipChildren(myRuleProcessor).name = "DuplicateElement". function DuplicateElement(){ this. with(myDocument){ var elements = xmlElements.item(0). . return true. this.apply = function(myElement. myRuleProcessor){ //Duplicates the part_number XML element. it can find elements by a specified attribute value. While the subset of XPath supported by XML rules cannot search the text of an element. __processRuleSet(elements. copying or moving XML element contents to XML attributes attached to their parent XML element can be very useful in XML-rule scripting.length != 0){ var myDocument = app. For the complete script. //This rule set contains a single rule.

parent.length != 0){ var myDocument = app.length != 0){ var myDocument = app. //Converts the XML element to an XML attribute of its parent XML element.CHAPTER 13: XML Rules XML Rules Examples 193 main(). “XML.texts. } } } In the previous XML rule. with(myDocument){ var elements = xmlElements.documents.item(0).” .item(0).xpath = "/devices/device/part_number". what if we want to move the XML element data into an attribute and remove the XML element itself? Use the convertToAttribute method.documents. function ConvertToAttribute(){ this.contents). function main(){ if (app.xpath = "/devices/device/part_number". this. __processRuleSet(elements. var myRuleSet = new Array (new AddAttribute). __processRuleSet(elements.convertToAttribute("PartNumber").item(0). as shown in the following script (from the ConvertToAttribute tutorial script): main(). function main(){ if (app.documents. with(myDocument){ var elements = xmlElements. myRuleProcessor){ //Use __skipChildren to prevent the XML rule processor from becoming //invalid when we convert the XML element to an attribute. myRuleSet).name = "AddAttribute". } } else{ alert("No open document"). this. return true.documents.apply = function(myElement. myElement.xmlAttributes. this.name = "ConvertToAttribute". Instead. // Define the apply function. return true. } function AddAttribute(){ this. __skipChildren(myRuleProcessor).add("part_number". } //Converts all part_number XML elements to XML attributes. as described in Chapter 12. myRuleSet).apply = function(myElement. myRuleProcessor){ myElement. we copied the data from an XML element into an XML attribute attached to its parent XML element. myElement. } } else{ alert("No open document"). } } } To move data from an XML attribute to an XML element. this.item(0). var myRuleSet = new Array (new ConvertToAttribute). use the convertToElement method.item(0).

see ReturningFalse.documents. while the second rule applies a different color to every other XML element (based on the state of a variable. The only difference between them is that the first rule applies a color and returns false. this. } } else{ alert("No open document").colors. 0]. 80.name = "ReturnFalse". 0]. 0.add({model:ColorModel.documents. new ReturnTrue). the XML-rules processor can apply other rules to the XML element. This script contains two rules that will match every XML element in the document.colors. the XML-rules processor does not apply any further XML rules to the matched XML element. 100. myCounter). with(myDocument){ var elements = xmlElements. myRuleProcessor){ with(myElement){ myElement.item(0). if (app.fillColor = app. For the complete script.item(0). function ReturnTrue(){ this.CHAPTER 13: XML Rules XML Rules Examples 194 Applying multiple matching rules When the apply function of an XML rule returns true. } // Leaves the XML element available to further processing. main().xpath = "//*". myRuleSet).process.item(0). } } //Adds a color to the text of every other element in the structure. colorValue:[100. } //Adds a color to the text of every element in the structure.documents. return false. The following script shows an example of an XML-rule apply function that returns false. name:"ColorA"}).texts.add({model:ColorModel.apply = function(myElement.colors. colorValue:[0. name:"ColorB"}) var myRuleSet = new Array (new ReturnFalse.item("ColorA").process.item(0). __processRuleSet(elements. function ReturnFalse(){ this. however. this. 80. //XPath will match on every XML element in the XML structure. When the apply function returns false. //Define two colors.name = "ReturnTrue". function main(){ myCounter = 0. var myColorA = myDocument. var myColorB = myDocument. .length != 0){ var myDocument = app.

documents.CHAPTER 13: XML Rules XML Rules Examples 195 //XPath will match on every XML element in the XML structure. myRuleProcessor){ with(myElement){ if(myCounter % 2 == 0){ myElement. } myCounter++.name = "AddAttribute". var myRuleSet = new Array(new FindAttribute). This script applies a color to the text of elements it finds. } //Now that the attributes have been added. with(myDocument){ var elements = xmlElements. myRuleSet). this. } function AddAttribute(){ this.item(0). __processRuleSet(elements.texts. __processRuleSet(elements. For the complete script.item(0). The following script shows how to match XML elements using attributes.fillColor = app.xpath = "/devices/device/part_number". } //Do not process the element with any further matching rules.apply = function(myElement.item(0). myRuleSet).item("ColorB").apply = function(myElement.item(0). var myRuleSet = new Array(new AddAttribute). you can either use attributes to find the XML elements you want or search the text of the matching XML elements. To get around this limitation. main(). } } else{ alert("No open document").documents.length != 0){ var myDocument = app. this.xpath = "//*". } } } Finding XML elements As noted earlier. myRuleProcessor){ .item(0). the subset of XPath supported by XML rules does not allow for searching the text contents of XML elements. this. find and format //the XML element whose attribute content matches a specific string. this. see FindXMLElementByAttribute. function main(){ if (app. return true. but a practical script would do more. with(myDocument){ var elements = xmlElements.colors.documents.

} } The following script shows how to use the findText method to find and format XML content (for the complete script. } } function myResetFindChangeGrep(){ app. this.documents.item(0).name = "FindByContent".parent. return true.documents. return true.documents.*?triangle/i this. var myRegExp = /triangle.test(myElement.texts.item(0). this.texts. } } function FindAttribute(){ this.length != 0){ var myDocument = app. function main(){ if (app.xmlElements. } function FindByContent(){ //Find descriptions that contain both "triangle" and "pulse".fillColor = app. this.contents) == true){ myElement. myRuleProcessor){ myElement. } return true.findGrepPreferences = NothingEnum.item(0).xpath = "/devices/device[@part_number = 'DS001']".item(0).swatches.name = "FindAttribute".add("part_number".*?pulse|pulse. __processRuleSet(elements.item(0).texts.item(0).xpath = "/devices/device/description".documents.item(0).item(0).nothing. see FindXMLElementByRegExp): main().item(-1). var myRuleSet = new Array (new FindByContent).contents).texts. app.CHAPTER 13: XML Rules XML Rules Examples 196 myElement.swatches. see FindXMLElementByFindText): .item(0). myElement. } } else{ alert("No open document").apply = function(myElement.nothing. myRuleSet).fillColor = app. myRuleProcessor){ if(myRegExp.item(-1).apply = function(myElement.xmlAttributes. //XPath will match on every description in the XML structure. this.changeGrepPreferences = NothingEnum. with(myDocument){ var elements = xmlElements. } } } The following script shows how to use a JavaScript regular expression (RegExp) to find and format XML elements by their content (for the complete script.

documents.findTextPreferences = NothingEnum.findText(). } function FindByFindText(){ this.item(0).item(0). } else{ alert("No open document").name = "FindByFindText". function main(){ if (app. myRuleSet).nothing. var myRuleSet = new Array (new FindByFindText).item(0). myResetFindText(). function main(){ if (app.length != 0){ myElement.documents.name = "FindByContent". __processRuleSet(elements.item(0). this.swatches.findWhat = "(?i)pulse.CHAPTER 13: XML Rules XML Rules Examples 197 main().xpath = "/devices/device/description".documents.length != 0){ var myDocument = app. this.*?pulse".item(-1). if(myFoundItems. app. //Search for the word "triangle" in the content of the element. myResetFindChangeGrep().documents. with(myDocument){ var elements = xmlElements. var myFoundItems = myElement. see FindXMLElementByFindGrep): main(). } } else{ alert("No open document"). .nothing.changeTextPreferences = NothingEnum.findGrepPreferences. with(myDocument){ var elements = xmlElements. myRuleSet).contents != ""){ //Clear the find text preferences. } myResetFindText().*?triangle|triangle.fillColor = app. this.texts.item(0).item(0). var myRuleSet = new Array (new FindByContent).item(0). __processRuleSet(elements.findWhat = "triangle".item(0). } myResetFindChangeGrep().documents.findTextPreferences.texts. app. myRuleProcessor){ if(myElement. } } function myResetFindText(){ app. } } The following script shows how to use the findGrep method to find and format XML content (for the complete script. app. } return true.length != 0){ var myDocument = app.texts. } function FindByContent(){ //Find descriptions that contain both "triangle" and "pulse".apply = function(myElement.

this. __processRuleSet(elements.xmlElements.length != 0){ myElement. if(myFoundItems.length != 0){ var myDocument = app. } } } . } } else{ alert("No open document"). or you run the risk of creating an endless loop.item(-1)).texts.item(0).add("VCOs").name = "ExtractVCO".xmlElements.item(0).texts.documents. myNewElement.move(LocationOptions.item(0). app. The following sample script shows how to duplicate a set of sample XML elements and move them to another position in the XML element hierarchy.fillColor = app.parent. myRuleProcessor){ var myFoundItems = myElement. var myMarkupTag = myDocument.xpath = "/devices/device/description".item(-1).apply = function(myElement.apply = function(myElement. function main(){ if (app.item(0). var myContainerElement = myDocument. } function ExtractVCO(){ var myNewElement.swatches.findGrepPreferences = NothingEnum. this.documents. this.item(0).item(0).xmlElements.xmlTags. } return true. Note that you must add the duplicated XML elements at a point in the XML structure that will not be matched by the XML rule.add(myMarkupTag). this. app.xmlElements. } } function myResetFindChangeGrep(){ app.item(0). myRuleSet).nothing.item(0). } } Extracting XML elements with XML rules XSLT often is used to extract a specific subset of data from an XML file.findGrep(). } } return true.contents == "VCO"){ myNewElement = myElement.texts.duplicate().item(0).documents.documents. this. main().changeGrepPreferences = NothingEnum. You can accomplish the same thing using XML rules. see ExtractSubset. with(myDocument){ var elements = xmlElements.CHAPTER 13: XML Rules XML Rules Examples 198 //XPath will match on every description in the XML structure. For the complete script.atEnd. myRuleProcessor){ with(myElement){ if(myElement. var myRuleSet = new Array (new ExtractVCO). // Define the apply function.xpath = "/devices/device/type".nothing.

add({name:"DeviceType". this. see XMLRulesApplyFormatting): main(). rearranging the order of XML elements. they can perform almost any action—from applying text formatting to creating entirely new page items.name = "ProcessDevice".documents. myDocument. new ProcessPrice). pointSize:12. myDocument. function main(){ if (app.add({name:"Price". leading:24. new ProcessName.verticalMeasurementUnits = MeasurementUnits. new ProcessPackageOne.paragraphStyles.viewPreferences. } .process.item(0). } return true. pointSize:10. XMLElementPosition. pages.add({name:"DeviceName".add({name:"PartNumber".paragraphStyles. } } else{ alert("No open document"). paragraphRuleAbove:true}). pointSize:10. pointSize:12. with(myDocument){ var elements = xmlElements. and documents. __processRuleSet(elements. new ProcessPartNumber. 0]. fontStyle:"Bold"}). 100.colors. var myRuleSet = new Array (new ProcessDevice.add({name:"Voltage".documents.length != 0){ var myDocument = app. leading:12}).paragraphStyles. fontStyle:"Bold". //Document set-up.points.add({model:ColorModel. new ProcessPackages. spaceBefore:24. myDocument. myDocument. new ProcessPackageType. pointSize:10. The following script adds static text and applies formatting to the example XML data (for the complete script.xpath = "/devices/device". new ProcessSupplyVoltage.item(0). myDocument. and adding text to XML elements. name:"Red"}). leading:12}). fillColor:"Red".viewPreferences.horizontalMeasurementUnits = MeasurementUnits. fontStyle:"Bold".paragraphStyles. new ProcessType.apply = function(myElement.paragraphStyles.afterElement). myDocument. myDocument. 100. myRuleSet). myDocument. Because XML rules are part of scripts. leading:12}). myDocument. myRuleProcessor){ with(myElement){ insertTextAsContent("\r".points. colorValue:[0.add({name:"DevicePackage". pointSize:24. The following XML-rule examples show how to apply formatting to XML elements using XML rules and how to create new page items based on XML-rule matching.paragraphStyles. this. leading:12}). } function ProcessDevice(){ this. leading:12.CHAPTER 13: XML Rules XML Rules Examples 199 Applying formatting with XML rules The previous XML-rule examples have shown basic techniques for finding XML elements.

//Add a return character at the end of the XML element.name = "ProcessSupplyVoltage".name = "ProcessType".item(0). myRuleProcessor){ var myDocument = app. //Note the positions at which we insert the static text. } return true.beforeElement).apply = function(myElement. } } //Adds static text around the "minimum" and "maximum" //XML elements of the "supply_voltage" XML element. XMLElementPosition.afterElement). } } function ProcessPartNumber(){ this. applyParagraphStyle(myDocument.beforeElement). XMLElementPosition. XMLElementPosition. this.xpath = "/devices/device/supply_voltage". with(myElement){ //Add static text at the beginning of the XML element. this.apply = function(myElement. XMLElementPosition. insertTextAsContent("\r".name = "ProcessName". XMLElementPosition.beforeElement). with(myElement){ insertTextAsContent("Circuit Type: ". applyParagraphStyle(myDocument. If we use //XMLElementPosition.item(0). insertTextAsContent("Supply Voltage: From ".paragraphStyles.afterElement). } return true. the static text appears //outside the XML elment (as a text element of the parent element). the static text //will appear inside the XML element. this. item("DeviceType")). this. } } function ProcessType(){ this. insertTextAsContent("Part Number: ".paragraphStyles. this. XMLElementPosition.item(0). this. myRuleProcessor){ var myDocument = app. item("PartNumber")).documents. myRuleProcessor){ var myDocument = app. . //If we use XMLElementPosition.xpath = "/devices/device/type". function ProcessSupplyVoltage(){ this.item(0).documents.paragraphStyles. item("DeviceName")).elementEnd. } return true.documents. applyParagraphStyle(myDocument.afterElement. myRuleProcessor){ var myDocument = app.documents. with(myElement){ //Add static text to the beginning of the voltage range.name = "ProcessPartNumber".xpath = "/devices/device/part_number".xpath = "/devices/device/name". this.apply = function(myElement. this.apply = function(myElement.CHAPTER 13: XML Rules XML Rules Examples 200 } function ProcessName(){ this.afterElement). with(myElement){ insertTextAsContent("\r". insertTextAsContent("\r".

} } return true. } } //Add the text "Package:" before the list of packages. myRuleProcessor){ var myDocument = app.afterElement).name = "ProcessPackageOne". XMLElementPosition.afterElement).xmlElements. insertTextAsContent(" volts".name = "ProcessPackages".name == "package"){ insertTextAsContent(".CHAPTER 13: XML Rules XML Rules Examples 201 with(myElement.item("Voltage")). XMLElementPosition. XMLElementPosition. } else{ insertTextAsContent("\r".xmlElements.paragraphStyles.afterElement). } } //Add commas between the package types. } return false. } //Add a return at the end of the XML element. this. applyParagraphStyle(myDocument. with(myElement){ if(myElement.item(0). with(myElement){ insertTextAsContent("-". myRuleProcessor){ var myDocument = app.xpath = "/devices/device/package/type".documents.item(-1)){ //Add static text to the beginning of the voltage range.item(0). function ProcessPackageOne(){ this. this. } return true. this. //Return false to let other XML rules process the element. this. XMLElementPosition.parent. XMLElementPosition.xmlElements. item("DevicePackage")).beforeElement).xpath = "/devices/device/package[1]". myRuleProcessor){ with(myElement){ insertTextAsContent("Package: ".nextItem(myElement). XMLElementPosition. insertTextAsContent("\r". this. this.xpath = "/devices/device/package".afterElement).name = "ProcessPackageType".documents. XMLElementPosition. function ProcessPackages(){ this. } } function ProcessPackageType(){ this.apply = function(myElement. } } . markupTag.afterElement).paragraphStyles. } return true. ".apply = function(myElement. } with(myElement.afterElement). applyParagraphStyle(myDocument.item(0)){ insertTextAsContent(" to ".apply = function(myElement.

for more information. } return true. } } } Creating page items with XML rules The following script creates new page items.apply = function(myElement. XMLElementPosition.item(0). } else{ myPage = myDocument. } return true. var myTextFrame = placeIntoFrame(myPage. myBounds). this. myPage).leadingOffset.item(0).name = "ProcessDevice".textFramePreferences.documents.name = "ProcessPrice".firstBaselineOffset = FirstBaseline.afterElement). and applies formatting. applyParagraphStyle(myDocument.item("Price")).pages. //Add a return at the end of the XML element. myRuleProcessor){ var myDocument = app.pages.length == 0){ myPage = myDocument. The first rule creates a new text frame for each “device” XML element: //Creates a new text frame on each page. XMLElementPosition. insertTextAsContent("\r". } } The “ProcessType” rule moves the “type” XML element to a new frame on the page: .apply = function(myElement. inserts the content of XML elements in the page items. see the complete script (XMLRulesLayout).xpath = "/devices/device/price".afterElement). myRuleProcessor){ var myDocument = app. adds static text.item(0). this.pages. this. with(myElement){ insertTextAsContent("\r".item(0).xpath = "/devices/device".add(). } var myBounds = myGetBounds(myDocument.beforeElement).paragraphStyles.textFrames. with(myElement){ insertTextAsContent("Price: $". this.documents. We include only the relevant XML-rule portions of the script here. myTextFrame.CHAPTER 13: XML Rules XML Rules Examples 202 function ProcessPrice(){ this. function ProcessDevice(){ this. if(myDocument. XMLElementPosition.

part number. myBounds[0]. this. 6.item(0).name = "ProcessType". return true. } } Successive rules move and format their content into container elements inside the row XML element. myRuleProcessor){ var myNewElement = myContainerElement. myBounds[2]].documents.pages. myBounds = [myBounds[0]-24. 6. myDocument.CHAPTER 13: XML Rules Creating Tables using XML Rules 203 //Creates a new text frame at the top of the page to contain the "type" XML element. myBounds[1]. .apply = function(myElement.item("Row")). myTextFrame. function ProcessDevice(){ this. applyParagraphStyle(myDocument. this.). as shown in the following script fragments (see XMLRulesTable).item("DeviceType")). In this example.fillColor = myDocument. the XML data we want to put into a table does not conform to this structure: it is likely that the XML elements we want to arrange in columns use heterogeneous XML tags (price.insetSpacing = [6.documents.xmlElements.swatches.xpath = "/devices/device/type". with(myElement){ var myBounds = myGetBounds(myDocument.xmlTags. this.add( app. To get around this limitation.apply = function(myElement. Typically. myRuleProcessor){ var myDocument = app. etc.paragraphStyles. a specific XML rule creates an XML element for each row.item(0). var myTextFrame = placeIntoFrame(myPage. } } Creating Tables using XML Rules You can use the convertElementToTable method to turn an XML element into a table. another for a cell.textFramePreferences. 6].item("Red") } return true. this. myTextFrame.name = "ProcessDevice".item(-1)). myBounds). we can “wrap” each XML element we want to add to a table row using a container XML element. This method has a limitation in that it assumes that all of the XML elements inside the table conform to a very specific set of XML tags—one tag for a row element.xpath = "//device[@type = 'VCO']". or column element. function ProcessType(){ this.

Scripting the XML-rules Processor Object While we have provided a set of utility functions in glue code. you cannot locate elements using XPath.” we can convert the container element to a table.CHAPTER 13: XML Rules Scripting the XML-rules Processor Object 204 function ProcessPrice(){ this.convertElementToTable(myRowTag.item(0). You might want do this to develop your own support routines for XML rules or to use the XML-rules processor in other ways. . (This script uses the same XML data file as the sample scripts in previous sections.xmlTags.beforeElement).xmlElements. var myNewElement = myContainerElement. this. } return true. and apply the rule using an XML-rules processor.jsx.insertTextAsContent("$".move(LocationOptions. XMLElementPosition.item("Column")). you also can script the XML-rules processor object directly. When you script XML elements outside the context of XML rules. myNewElement). myElement.xmlElements. however.xpath = "//device[@type = 'VCO']/price". see XMLRulesProcessor.) For the complete script.add(app.atBeginning.item(-1) . create an XML rule that does nothing more than return matching XML elements. myColumnTag).name = "ProcessPrice". as shown in the following script. var myTable = myContainerElement.apply = function(myElement.documents. this. You can. } } } Once all of the specified XML elements have been “wrapped. myRuleProcessor){ with(myElement){ __skipChildren(myRuleProcessor). var myElement = myElement.

endProcessingRuleSet(). function mySimulateXPath(myXPath){ var myXMLElements = new Array. item(0). function main(){ var myXPath = ["/devices/device"].add(myXPath). myXMLElements.element.CHAPTER 13: XML Rules Scripting the XML-rules Processor Object 205 main(). try{ var myMatchData = myRuleProcessor.push(myElement).endProcessingRuleSet(). } myRuleProcessor.item(0)). while(myMatchData != undefined){ var myElement = myMatchData.findNextMatch(). var myRuleProcessor = app. var myXMLMatches = mySimulateXPath(myXPath). //At this point.startProcessingRuleSet(app. throw myError. return myXMLElements.documents.remove().remove().xmlElements. myRuleProcessor. } catch (myError){ myRuleProcessor.xmlRuleProcessors. myMatchData = myRuleProcessor. myXMLMatches contains all of the XML elements //that matched the XPath expression provided in myXPath. } } } . myRuleProcessor.

changes. Whenever anyone adds. accept.changes. var myChange = myStory. install. deletes.documents. accept changes. or moves text within an existing story.trackChanges   If true. track changes is turned on. We also assume that you have some knowledge of working with text in InDesign and understand basic typesetting terms.length. show.item(0). //Story.item(0). we use the previousItem method to navigate to the change following the insertion point: 206 . if(myChangeCount>1) { var myChange0 = myStory.nextItem(myChange). refer to GetTrackchange). if(myStory.changes. and reject changes using scripting. All changes are recorded and visualized to make it easier to review a document. The following script show how to navigate the tracked changes (for the complete script. } } In the script below. We assume that you have already read Adobe InDesign CS5 Scripting Tutorial and know how to create. The script below uses the nextItem method to navigate to the change following the insertion point: var myDocument = app. and run a script. the change is marked in galley and story views.stories. var myStory = myDocument. the user can navigate sequentially through tracked changes.item(0). Navigating tracked changes If the story contains a record of tracked changes. and reject changes as a document moves through the writing and editing process.trackChanges==true) { var myChangeCount = myStory.14 Track Changes Writers can track. Tracking Changes This section shows how to navigate tracked changes. This tutorial shows how to script the most common operations involving tracking changes. hide.

item(0). deleted.item(0). track changes is turned on. refer to AcceptChange): var myDocument = app.trackChanges   If true. refer to RejectChange): var myDocument = app. refer to GetChangeInfo): .changes.previousItem(myChange). The following script shows the information of a tracked change (for the complete script.trackChanges==true) { var myChangeCount = myStory. if(myStory.Track Changes Tracking Changes 207 var myDocument = app. var myStory = myDocument.item(0). var myChange = myStory.reject() . var myStory = myDocument.item(0). by you or others. myChange.item(0).item(0).stories. var myChange = myStory.stories. In the following script.item(0). You can accept and reject changes—added. if(myChangeCount>1) { var myChange0 = myStory.changes.documents.stories.accept() . Information about tracked changes Change information includes include date and time.item(0). the change is rejected (for the complete script. the change-tracking feature enables you to review all changes and decide whether to incorporate them into the story.changes.documents. var myChange = myStory. var myStory = myDocument.changes. the change is accepted (for the complete script. //Story. or moved text—made by any user.documents. } } Accepting and reject tracked changes When changes are made to a story. In the following script. myChange.length.lastItem().changes.

refer to GetChangePreference): var myTrackChangesPreference = app. backgroundColorForMovedText = UIColors. var myTextVariableInstances = myChange.CHANGE_USES_CHANGE_PREF_COLOR. var myCharacters = myChange. . Preferences for Tracking Changes Track-changes preferences are user settings for tracking changes.item(0). var myColor = backgroundColorForDeletedText. //InsertionPoints A collection of insertion points. deletedTextColorChoice = ChangeTextColorChoices. var myInsertionPoints = myChange.textVariableInstances. backgroundColorForAddedText = UIColors.characters. var myStoryOffset = myChange.paragraphs  (Read Only) A collection of paragraphs. //Change.RIGHT_ALIGN  (Read Only) Change bars are in the right margin locationForChangeBar = ChangebarLocations. var myChange = myStory. For example.gray.LEFT_ALIGN  (Read Only) Change bars are in the left margin. var myTextColumns = myChange. you can define which changes are tracked (adding.red. //ChangeTypes.textVariableInstances  (Read Only) A collection of text variable instances.texts. var myParagraphs = myChange. var myWords = myChange.textColumns  (Read Only) A collection of text columns.CHANGE_USES_CHANGE_PREF_COLOR. //ChangeMarkings.CHANGE_BACKGROUND_USES_CHANGE_PREF_COLOR. deleting.item(0).storyOffset.texts  (Read Only) A collection of text objects. //ChangebarLocations. //ChangeTypes.trackChangesPreferences. var myUserName = myChange. or moving text).userName.words. //ChangeTypes.textStyleRanges.Track Changes Preferences for Tracking Changes 208 var myDocument = app. var myDate = myChange. backgroundColorForDeletedText = UIColors.changeType. //Change.textStyleRanges  (Read Only) A collection of text style ranges. and you can have changes identified with colored change bars in the margins. var myTexts = myChange.changes. You can specify the appearance of each type of tracked change. addedTextColorChoice = ChangeTextColorChoices.paragraphs. var myLines = myChange.MOVED_TEXT  (Read Only) Moved text.lines. //ChangeMarkings. var myStory = myDocument.stories.documents. //Change. var myChangeTypes = myChange. //Change. deletedBackgroundColorChoice =ChangeBackgroundColorChoices. changeBarColor = UIColors. with(myTrackChangesPreference) { addedBackgroundColorChoice = ChangeBackgroundColorChoices.STRIKETHROUGH  (Read Only) Uses a strikethrough to mark changed text. //ChangebarLocations. //Change.date. //Change.textColumns.pink.OUTLINE  (Read Only) Outlines changed text.charcoal. //ChangeMarkings.insertionPoints. //Characters A collection of characters.NONE  (Read Only) Does not mark changed text. The following script shows how to set and get these preferences (for the complete script.lines  (Read Only) A collection of lines.DELETED_TEXT  (Read Only) Deleted text. var myTextStyleRanges = myChange.LEFT_ALIGN.DELETED_TEXT  (Read Only) Deleted text.CHANGE_BACKGROUND_USES_CHANGE_PREF_COLOR.item(0).

showChangeBar = true.yellow.Track Changes Preferences for Tracking Changes 209 //ChangeMarkings. markingForAddedText = ChangeMarkings. spellCheckDeletedtext = true. } .CHANGE_BACKGROUND_USES_CHANGE_PREF_COLOR.green. textColorForAddedText = UIColors. movedBackgroundColorChoice = ChangeBackgroundColorChoices.blue. shhowDeletedText = true. showAddedText = true.UNDERLINE_SINGLE. markingForMovedText = ChangeMarkings.OUTLINE.UNDERLINE_SINGLE  (Read Only) Underlines changed text.STRIKETHROUGH. showMovedText = true. movedTextColorChoice = ChangeTextColorChoices. markingForDeletedText = ChangeMarkings.CHANGE_USES_CHANGE_PREF_COLOR. textColorForDeletedText = UIColors. textColorForMovedText = UIColors.

Sign up to vote on this title
UsefulNot useful