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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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 .

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

CHAPTER 10: Working with Preflight Available Rules 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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Sign up to vote on this title
UsefulNot useful