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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

and each document includes at least one layer. for example. The basic properties of a layer are shown in the column at the left of the figure. it will not appear in the pageItems collection. The former is a collection containing only the top-level page items in a layer.. regardless of their location in the object hierarchy. You can think of layers as transparent planes stacked on top of each other. If a page item is inside a group. or spread. not bound to specific pages or spreads. the objects that may be contained by the layer object. You also can use layers as an organizational tool. putting one type of content on a given layer or set of layers. 50 . 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. regardless of their location in the object hierarchy. Layers are document wide. A page item inside a group on the layer would appear in the allPageItems collection. in addition to finding it inside a layer object). the allPageItems collection is a flattened collection of all page items assigned to the layer. It uses the JavaScript form of the object names. at the right. text object. Understanding the Layer Object Model The following figure shows the layer object model. page.4 Working with Layers InDesign’s layers are the key to controlling the stacking order of objects in your layout. 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 allGraphics property contains all graphics stored in page items assigned to the layer. In contrast. the object hierarchy is the same in all scripting languages. It is important to note the distinction between the page-items collection and the allPageItems collection. however. 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.g. Similarly.

see the InDesign online help. When you create a new layer.layers.add(). 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. . var myLayer = myDocument. see AddLayer.) //Given a document "myDocument".CHAPTER 4: Working with Layers Scripting Layers 51 Scripting Layers In InDesign’s user interface. and merge layers using the Layers panel. Creating layers The following script fragment shows how to create a new layer. you add. the layer appears above all other layers in the document.) This section shows how to accomplish these tasks using InDesign scripting. duplicate. (For more on assigning objects to a layer. delete.. (For the complete script. This section describes the most common ways to refer to layers. Referring to layers InDesign scripting offers several ways to refer to a layer object. rearrange..

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

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

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

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

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

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

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

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

When you create a compound path. the type of the resulting object is polygon.duplicate([12. 12]). 12 points vertically. To move the object to another while retaining the original. Use the duplicate method to create a copy of a page item.item(0)). Every page . var myDuplicate = myRectangle.e. var myDocument = app. Using Pathfinder operations The InDesign Pathfinder features offer ways to work with relationships between page items on an InDesign page. //Given a polygon "myPolygon".add(). 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(myPage).. //Given a rectangle "myRectangle" and an Oval "myOval". regardless of the types of the objects used to create the compound path. use the duplicate method (see below). [12. it is deleted from the original document. You can merge the paths of page items.documents. 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. 12). more likely to fail) than scripts that use duplicate and move. var myPageItems = myPolygon.releaseCompoundPath().. or subtract the area of one page item from another page item. To release a compound path and convert each path in the compound path into a separate page item.add(). or to another document entirely).pages.. as shown in the following script fragment (for the complete script.. //Duplicate the rectangle to another page (rectangle appears at (0. //Duplicate the rectangle and move the duplicate *by* 12 //points horizontally. //Duplicate the rectangle to another document.. You can also use copy and paste in InDesign scripting. You can do this in InDesign scripting using the makeCompoundPath method of a page item.pages. myRectangle. Whenever possible. //Given a reference to a rectangle "myRectangle". as shown in the following script fragment (for the complete script.0).documents..makeCompoundPath(myOval).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. //Absolute move: var myDuplicate = myRectangle. 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. //Relative move (note undefined first parameter): var myDuplicate = myRectangle. use the releaseCompoundPath method of a page item. try to write scripts that do not depend on the current view or selection state.item(0). refer to the MakeCompoundPath script). //Duplicate the rectangle and move the //duplicate to the location (12.duplicate(undefined. refer to the ReleaseCompoundPath script). var myPage = app. or create a new page item from the area of intersection of two or more page items.duplicate(myDocument. the duplicate method creates a “clone” of an object in the same location as the original object. This means that scripts that use copy and paste tend to be more fragile (i. By default. var myDuplicate = myRectangle. 12]).

The excludeOverlapPath method creates a new path based on the non-intersecting areas of two or more overlapping page items. myRectangle. The intersectPath method creates a new page item from the area of intersection of two or more page items. myRectangle.excludeOverlapPath(myOval).. myRectangle. refer to ConvertShape). . as demonstrated in the following script fragment (for the complete script. myOval. To merge two page items into a single page item.. refer to IntersectPath).intersect(myOval). In InDesign scripting. as shown in the following script fragment (for the complete script.. //Given a rectangle "myRectangle" and an Oval "myOval". MinusBack. page items support the convertShape method. refer to ExcludeOverlapPath). myRectangle. refer to AddPath). for example. //Given a rectangle "myRectangle" and an Oval "myOval". //Given a rectangle "myRectangle".. //Given a rectangle "myRectangle" and an Oval "myOval".. and SubtractPath. //Given a rectangle "myRectangle" and an Oval "myOval". as shown in the following script fragment (for the complete script. myRectangle. refer to MinusBack)..convertToRoundedRectangle).subtractPath(myRetangle). The minusBack method removes the area of intersection of the back-most object from the page item or page items in front of it..convertShape(ConvertShapeOptions.. 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.. as shown in the following script fragment (for the complete script. The convertShape method also provides a way to open or close reverse paths. refer to SubtractPath). IntersectPath.addPath(myOval). Note that it is very likely that the type of the object will change after you apply one of the Pathfinder operations.. 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). //Given a rectangle "myRectangle" and an Oval "myOval". ExcludeOverlapPath. you would use something like the approach shown in the following fragment (for the complete script.CHAPTER 5: Working with Page Items Duplicating and Moving Page Items 61 item supports the following methods related to the Pathfinder features: AddPath... 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). as shown in the following script fragment (for the complete script. as shown in the following script fragment (for the complete script. The subtractPath method removes the area of intersection of the frontmost object from the page item or page items behind it. refer to OpenPath).minusBack(myOval).

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

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

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

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

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

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

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

var myRectangleH = myRectangleG.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.transformationMatrices.pasteboardCoordinates. AnchorPoint.. Resize and Reframe In addition to scaling page items using the transform method.transformAgain().pasteboardCoordinates. var myBounds = myRectangle.transformAgain(). var myRectangleD = myRectangleC. ResizeMethods.duplicate().transformAgain(). see TransformAgain. For the complete script. There are four methods for applying transformations again: transformAgain transformAgainIndividually transformSequenceAgain transformSequenceAgainIndividually The following script fragment shows how to use transformAgain. myRectangleG. myRectangleF. var myRectangleB = myRectangleA.add({geometricBounds:[myY1-12. var myRectangleF = myRectangleE. var myRectangleE = myRectangleD.innerCoordinates. //Given a reference to a rectangle "myRectangle". myY1+12.topLeftAnchor]. (For the complete script. var myTransformationMatrix = app.centerAnchor. The following script fragment shows how to use the resize method. var myRectangleG = myRectangleF. myDuplicate. you can also change the size of the shape using two other methods: resize and reframe. [[0..item(0).geometricBounds.transformAgain().duplicate(). var myDuplicate = myRectangle. myRectangleB.duplicate(). myRectangleF. myRectangleD.rectangles. myX1+12]}).resize(CoordinateSpaces.add({counterclockwiseRotationAngle:45}). myRectangleA. . var myY1 = myBounds[0]. AnchorPoint. var myRectangleC = myRectangleB.centerAnchor.duplicate(). true).duplicate(). myRectangleE. myTransformationMatrix). myTransformationMatrix). myRectangleB. var myX1 = myBounds[1]. myX1-12. myRectangleC.0].duplicate().transform(CoordinateSpaces. [2.) var myRectangle = myPage. AnchorPoint.transformAgain().duplicate().transformAgain(). myRectangleH. AnchorPoint.transform(CoordinateSpaces.transformAgain(). 2]).centerAnchor. undefined.rectangles. myRectangleH. see Resize. you can do so using scripting. var myRectangleA = myPage. myRectangleD.multiplyingCurrentDimensionsBy.transformAgain().transform(CoordinateSpaces. myTransformationMatrix.duplicate().pasteboardCoordinates.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.

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

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

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

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

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

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

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 + ">";

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

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

item(0) textFrames. page.item(0) stories.item(0) For any text stream object.item(0) paragraphs. the parent of the object is the story containing the object. 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. .item(0) characters.item(0) textFrames.item(0) characters.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. use the parentTextFrames property.item(0) characters.CHAPTER 6: Text and Type Understanding Text Objects 82 document story spread.item(0) paragraphs. To get a reference to the text frame (or text frames) containing the text object.

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

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

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

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

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

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

oval. myCounter >= 0.length-1. or graphic line) at a specific location in text (usually an insertion point).duplicate(). second. //Duplicate each text frame in the story. } } Creating an anchored frame To create an anchored frame (also known as an inline frame).parentStory). switch(mySelection. see AnchoredFrame): .textContainers. independent stories. } break. //Process the selection.selection[0]. Iterate backwards to //avoid invalid references. } } function myRemoveFrames(myStory){ //Remove each text frame in the story.selection.textContainers. see SplitStory): if(app. myCounter --){ myStory. for(var myCounter = myStory. delete the original text frames.textContainers[myCounter].length != 0){ //Get the first item in the selection. each containing one unlinked text frame (for the complete script. polygon.length != 1){ //Splitting the story is a two-step process: first. myCounter >= 0.textContainers. do nothing. otherwise.length != 0){ if(app. if(mySelection.remove(). do nothing. myTextFrame. for(var myCounter = myStory.textContainers[myCounter]. you can create a text frame (or rectangle.documents. do something. var mySelection = app.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.constructor. If text or a text frame is //selected. } } } Here is the mySplitStory function referred to in the preceding script: function mySplitStory(myStory){ var myTextFrame. myCounter --){ myTextFrame = myStory.parentStory).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.length-1. mySplitStory(mySelection. duplicate //the text frames. The following script fragment shows an example (for the complete script.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

idJavascript For myCounter = 1 to 100 Rem Add a page to the document.idNo End If Next .idJavascript If(myCounter = 100) Then myString = "#targetengine ""session""" & vbCr myString = myString & "myProgressPanel.hide(). idScriptLanguage." & vbcr myInDesign." & vbcr myString = myString & "myProgressPanel. the progress bar Rem will go by too quickly.DoScript myString.value = " myString = myString & cstr(myCounter) & "/myIncrement.DoScript myString. idScriptLanguage. idScriptLanguage.Close idSaveOptions.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.myProgressBar.Pages. myInDesign." & vbcr myString = myString & "myProgressPanel. 400).value = 0.Documents.Add myString = "#targetengine ""session""" & vbCr myString = myString & "myProgressPanel. Set myDocument = myInDesign." & vbcr myInDesign.idJavascript myDocument.Documents. myString = "#targetengine ""session""" & vbCr myString = myString & "myCreateProgressPanel(100." & vbcr myInDesign. see CallProgressBar): Rem Create a document and add pages to it-Rem if you do not do this.Add Rem Note that the JavaScripts must use the "session" Rem engine for this to work.show().Item(1).DoScript myString.myProgressBar.

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

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

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

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

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

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

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

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

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

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

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

//Open a new text file. .length.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 . myTextFile. myCounter++){ myTextFile. if(myTextFile != null){ //Open the file with write access.. for(var myCounter = 0. var myTextFile = File. myCounter < myMenuActionNames.everyItem().menuActions.saveDialog("Save Menu Action Names As". These scripts can be very slow.writeln(myMenuActionNames[myCounter]). //If the user clicked the Cancel button. run the following script fragment (from the GetMenuActions tutorial script): var myMenuActionNames = app. } To create a list (as a text file) of all available menus.open("w"). To create a list (as a text file) of all menu actions..name. run the following script fragment (for the complete script. see GetMenuNames). undefined). as there are many menu names in InDesign.. eventListener eventListener .. the result is null.close(). } myTextFile.

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):

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

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

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

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

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

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

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

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

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

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

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

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

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

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_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 .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.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 .

5 .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.01 612 ADBE_ScaledGraphics Data Type Real Name max_scale Default value 100.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.

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 .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.

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

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

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

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

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

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

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

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

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

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

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

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. as shown in the following script fragment (for the complete script.pageTransitionDirection = PageTransitionDirectionOptions.medium. myCounter < myDocument. as shown in the next two lines: //myDocument.spreads. and you'll see the page transitions. for(var myCounter = 0.pageTransitionDuration = PageTransitionDurationOptions. } //Export the document to SWF..spreads.pageTransitionType = PageTransitionTypeOptions.length. myCounter++){ myDocument. //Given a document "myDocument" containing at least two spreads.item(myCounter). Adding page transitions using scripting is easy.wipeTransition (for example).leftToRight. If you chose //PageTransitionTypeOptions. //myDocument. you would be //able to set those options.item(myCounter).spreads. .pageTurnTransition.item(myCounter). refer to PageTransitions)..spreads. //This page transition option does not support the pageTransitionDirection //or pageTransitionDuration properties.

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

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”).

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

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

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

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

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

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

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 );

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

including one that uses __processChildren. Every element is processed twice. see ProcessChildren.) .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. (For the complete script. The rule set includes two rules that match every element.

documents.stories.insertionPoints.stories.contents = myElement. the rule can change the XML structure of the document. this.item(0).apply = function(myElement.name = "NormalRule".insertionPoints. myRuleProcessor){ app. create a separate rule that matches and processes the ancestor XML element. this.documents. } //End of apply function } function ProcessChildrenRule(){ this. 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. // Define the apply function.item(-1).CHAPTER 13: XML Rules Overview 182 function NormalRule(){ this.item(0).item(0).name = "ProcessChildrenRule".item(0). return false.value + "\r".contents = myElement. this. //XPath will match on every part_number XML element in the XML structure.xmlAttributes. myRuleProcessor){ __processChildren(myRuleProcessor).xpath = "//XMLElement".value + "\r".item(0). if the affected XML elements in the structure are part of the current path of the XML-rules processor. This can conflict with the process of applying other rules.xmlAttributes. this. .item(0).item(-1). return false.apply = function(myElement.xpath = "//XMLElement". // Define the apply function. app. } //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. //XPath will match on every part_number XML element in the XML structure. To prevent errors that might cause the XML-rules processor to become invalid.

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

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

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. 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. we use the product list of an imaginary integrated-circuit manufacturer. import the XMLRulesExampleData. When you import the XML. For our example. turn on the Do Not Import Contents of Whitespace-Only Elements option in the XML Import Options dialog box. run the following script before you run each sample XML-rule script (see the XMLRulesExampleSetup.xml data file into a document. Alternately.jsx script file): . XML rules are closely tied to the structure of the XML in a document. In the remainder of this chapter. This means it is almost impossible to demonstrate a functional XML-rules script without having an XML structure to test it against. Save the file. then choose File > Revert before running each sample script in this section. starting with a very simple script and building toward more complex operations. Setting up a sample document Before you run each script in this chapter. we present a series of XML-rules exercises based on a sample XML data file.

var myX2 = myWidth .activeScript. return [myY1. myDocument.xmlElements.documentPreferences. myBounds).pages.jsx // main().allowTransform = false.documentPreferences.placeIntoFrame(myDocument.right. } } } 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. myX2]. myX1. } function myGetScriptPath() { try { return app. function main(){ var myDocument = app.myPage.xmlImportPreferences.top.xmlImportPreferences.marginPreferences.path + "/XMLRulesExampleData. var myBounds = myGetBounds(myDocument.item(0).xml" myDocument.left. For the complete script.pageWidth.marginPreferences. var myHeight = myDocument.pages. } catch(myError){ return File(myError. The XML-rule set contains one rule. var myFilePath = myScriptPath.documents.marginPreferences.importXML(File(myFilePath)). myY2.item(0)).fileName).CHAPTER 13: XML Rules XML Rules Examples 186 //XMLRuleExampleSetup. myDocument.item(0). function myGetBounds(myDocument.myPage.marginPreferences.add(). .pageHeight.bottom. var myY2 = myHeight . var myScriptPath = myGetScriptPath(). see AddReturns.ignoreWhitespace = true. myPage){ var myWidth = myDocument. var myX1 = myPage. var myY1 = myPage. myDocument. myDocument.

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

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

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

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

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

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

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

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

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

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

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

} } else{ alert("No open document").texts.xmlElements.documents. app.name = "ExtractVCO".item(0). myNewElement. 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. } } Extracting XML elements with XML rules XSLT often is used to extract a specific subset of data from an XML file.length != 0){ myElement.findGrep(). or you run the risk of creating an endless loop.add("VCOs").move(LocationOptions. myRuleProcessor){ with(myElement){ if(myElement.item(0). myRuleProcessor){ var myFoundItems = myElement.xmlElements.item(0).documents.documents.CHAPTER 13: XML Rules XML Rules Examples 198 //XPath will match on every description in the XML structure. } return true.nothing. var myRuleSet = new Array (new ExtractVCO).xpath = "/devices/device/description".add(myMarkupTag). } } return true.findGrepPreferences = NothingEnum. function main(){ if (app.parent. this. app. For the complete script. this.xmlElements.documents. var myMarkupTag = myDocument. } function ExtractVCO(){ var myNewElement. } } } . with(myDocument){ var elements = xmlElements. this. see ExtractSubset. 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.contents == "VCO"){ myNewElement = myElement.texts.duplicate().atEnd.nothing.xpath = "/devices/device/type".item(0).item(-1)). var myContainerElement = myDocument.item(0). this.apply = function(myElement. __processRuleSet(elements. } } function myResetFindChangeGrep(){ app. main().apply = function(myElement.xmlTags.swatches.fillColor = app. // Define the apply function.item(0).item(-1). if(myFoundItems.length != 0){ var myDocument = app.item(0). You can accomplish the same thing using XML rules.item(0).item(0).xmlElements.changeGrepPreferences = NothingEnum. this.texts. myRuleSet).

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

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

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

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

as shown in the following script fragments (see XMLRulesTable).item(0).pages.swatches. part number. 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. } } Successive rules move and format their content into container elements inside the row XML element. myRuleProcessor){ var myDocument = app. myTextFrame. Typically. myTextFrame.documents. this.xpath = "/devices/device/type". 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. a specific XML rule creates an XML element for each row. with(myElement){ var myBounds = myGetBounds(myDocument.). myBounds).xpath = "//device[@type = 'VCO']".item("DeviceType")). To get around this limitation. function ProcessType(){ this.apply = function(myElement.textFramePreferences. } } Creating Tables using XML Rules You can use the convertElementToTable method to turn an XML element into a table.item("Red") } return true.insetSpacing = [6. return true. or column element. myBounds[0].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. myDocument.item(-1)). 6. etc. var myTextFrame = placeIntoFrame(myPage. this. another for a cell. myBounds[2]]. 6.xmlTags.apply = function(myElement. In this example. .fillColor = myDocument. we can “wrap” each XML element we want to add to a table row using a container XML element.name = "ProcessType".item("Row")). this.documents. myBounds[1]. this.add( app.paragraphStyles. myRuleProcessor){ var myNewElement = myContainerElement. function ProcessDevice(){ this. myBounds = [myBounds[0]-24. 6]. applyParagraphStyle(myDocument.name = "ProcessDevice".item(0).xmlElements.

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

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

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

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

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

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

Master your semester with Scribd & The New York Times

Special offer for students: Only $4.99/month.

Master your semester with Scribd & The New York Times

Cancel anytime.