<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2enclosuresfull.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:media="http://search.yahoo.com/mrss/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><title>Rorohiko</title><link>http://rorohiko.blogspot.com/</link><description>Kris Coppieters' blog</description><language>en</language><managingEditor>kris@rorohiko.com (Kris Coppieters)</managingEditor><lastBuildDate>Fri, 30 Oct 2009 12:43:39 PDT</lastBuildDate><generator>Blogger http://www.blogger.com</generator><openSearch:totalResults xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/">18</openSearch:totalResults><openSearch:startIndex xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/">1</openSearch:startIndex><openSearch:itemsPerPage xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/">25</openSearch:itemsPerPage><media:copyright>(c) Rorohiko Ltd.</media:copyright><media:thumbnail url="http://www.rorohiko.com/logo.png" /><media:keywords>printing,prepress,automation,InDesign,Adobe,CS,CS2,CS3,Rorohiko,plug,in,plugin,software,consultancy,design,desktop,publishing,PDF,Acrobat,XPress,QuarkXPress,XTension</media:keywords><media:category scheme="http://www.itunes.com/dtds/podcast-1.0.dtd">Technology</media:category><media:category scheme="http://www.itunes.com/dtds/podcast-1.0.dtd">Arts/Design</media:category><media:category scheme="http://www.itunes.com/dtds/podcast-1.0.dtd">Education/Training</media:category><media:category scheme="http://www.itunes.com/dtds/podcast-1.0.dtd">Technology/Software How-To</media:category><itunes:owner><itunes:email>kris@rorohiko.com</itunes:email><itunes:name>Kris Coppieters</itunes:name></itunes:owner><itunes:author>Kris Coppieters</itunes:author><itunes:explicit>no</itunes:explicit><itunes:image href="http://www.rorohiko.com/logo.png" /><itunes:keywords>printing,prepress,automation,InDesign,Adobe,CS,CS2,CS3,Rorohiko,plug,in,plugin,software,consultancy,design,desktop,publishing,PDF,Acrobat,XPress,QuarkXPress,XTension</itunes:keywords><itunes:subtitle>Automation for Printing and Prepress</itunes:subtitle><itunes:summary>Automation for printing and prepress. Opinions, musings and ideas.</itunes:summary><itunes:category text="Technology" /><itunes:category text="Arts"><itunes:category text="Design" /></itunes:category><itunes:category text="Education"><itunes:category text="Training" /></itunes:category><itunes:category text="Technology"><itunes:category text="Software How-To" /></itunes:category><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/Rorohiko" type="application/rss+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item><title>InDesign Scripters and Plug-In Developers: How To Avoid Confusing File Duplications</title><link>http://feedproxy.google.com/~r/Rorohiko/~3/wVwKk7T87Kc/indesign-scripters-and-plug-in.html</link><author>kris@rorohiko.com (Kris Coppieters)</author><pubDate>Tue, 27 Oct 2009 13:15:44 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-1401434775260820755.post-6852532564100897277</guid><description>In short: how to avoid copying or shuffling scripts and plug-ins during development on Mac or Windows.&lt;br /&gt;&lt;br /&gt;When it comes to scripts or plug-ins, Mac alias files can be used as if they are 'the real thing' - InDesign will treat an alias file as if it &lt;span style="font-style: italic;"&gt;is&lt;/span&gt; the script or plug-in it is referring to. I'll explain how you can use that feature to your advantage.&lt;br /&gt;&lt;br /&gt;Sadly enough, a Windows shortcut file is not treated with the same respect by InDesign - a Windows shortcut file is simply ignored, so shortcuts are out.&lt;br /&gt;&lt;br /&gt;Luckily, Windows has a 'hard-linking' feature that can be used in the same way as Mac alias files - I'll explain that too.&lt;br /&gt;&lt;br /&gt;The basic idea is to avoid 'scattering' copies of your script or plug-in around your hard disk. As soon as you start copying stuff around, it becomes easy to lose track of which is which, and in the heat of the moment, you might get older and newer versions mixed up.&lt;br /&gt;&lt;br /&gt;A typical scenario would be: you're creating a script that needs to work both on InDesign CS3 and InDesign CS4. You're testing and debugging - and each time you want to swap between CS3 and CS4, you need to copy the script in progress from one Scripts folder to the other.&lt;br /&gt;&lt;br /&gt;And then the phone rings, and you're caught in mid-swap. After the phone call, you forgot: did you complete the copy or not? So, where is the most recent version - in the CS3 folder or in the CS4 folder? Frustrating, isn't it?&lt;br /&gt;&lt;br /&gt;To avoid doing 'the shuffle',  you can instead store a single 'master copy' of your plug-in or script somewhere on your hard disk.&lt;br /&gt;&lt;br /&gt;If you are using a source code control system like SVN or CVS, the master copy would probably reside somewhere in a folder structure managed with the source code control system.&lt;br /&gt;&lt;br /&gt;Then, instead of copying the script or plug-in to it's 'active location' (e.g. one of the InDesign plug-ins folder, or one of the InDesign scripts folders), you instead create a 'stand-in' which always refers back to the master copy of the file.&lt;br /&gt;&lt;br /&gt;On Mac, you can use an alias file for that - pretty easy. Create an alias of the script or plug-in and plunk the alias into the proper InDesign subfolder - and everything will work as if the 'real thing' was there.&lt;br /&gt;&lt;br /&gt;On Windows, you might be tempted to try shortcut files - but that does not work. Instead, you need to use a hard link, which you can create from a command-line window with the following command:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;fsutil hardlink create &lt;/span&gt;&lt;/span&gt;&lt;destination&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;original&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;[destination] [original]&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;where [destination] is the path of the hard link to be created and [original] is the path of the original file. Depending on your setup and Windows OS version, you might need to launch the command-line window as user 'Administrator', so you have enough privileges.&lt;br /&gt;&lt;br /&gt;You can use this command to create hard links to &lt;span style="font-style: italic;"&gt;folders &lt;/span&gt;as well as &lt;span style="font-style: italic;"&gt;files &lt;/span&gt;- but I recommend you &lt;span style="font-style: italic;"&gt;only &lt;/span&gt;use it for hard links to &lt;span style="font-style: italic;"&gt;files&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Also keep in mind that this command only works on NTFS volumes (so FAT volumes are out), and both original and destination need to be on the same volume - but in most cases that's all you need.&lt;br /&gt;&lt;br /&gt;Hard links are a low-level NTFS feature, and hard links to &lt;span style="font-style: italic;"&gt;folders &lt;/span&gt;are not well supported in Explorer - and as a result, they're very &lt;span style="font-style: italic;"&gt;dangerous &lt;/span&gt;things - they don't behave like Windows shortcuts, and that is where the danger lies.&lt;br /&gt;&lt;br /&gt;Suppose you had created a hard link from a folder, and then you attempt to delete the hard link later on. Doing that in Explorer would actually also delete all the items that reside in the original folder - not what you'd expect. Explorer treats the hard link as the real thing, and when you delete a folder, it simple-mindedly will empty the folder first - blissfully unaware that the folder is still being used via the original directory entry.&lt;br /&gt;&lt;br /&gt;Once a hard link to a folder is created, it's not easy to get rid of without also losing the contents of the folder.&lt;br /&gt;&lt;br /&gt;In short: avoid issues - only create hard links to files on Windows; that's much safer.&lt;br /&gt;&lt;br /&gt;There's another caveat with regards to hard links on Windows. If you use a hard link to a script file, you must make sure that the text editor program you use does &lt;span style="font-style: italic;"&gt;not&lt;/span&gt; create backup files because that tends to mess up the hard link - typically, the text editor will simply rename the original file 'test.jsx' to 'test.jsx.bak' or so - taking the hard link along, so it now refers to the .bak file instead of the modified .jsx file.&lt;br /&gt;&lt;br /&gt;Turn the backup feature off, and all will be well. I've tried it with Notepad and ExtendScript toolkit, and things seem to work well: if I edit the script via its hard link, the original script is updated as well. I also use UEStudio as a text editor - and at first I ran into problems because this editor makes .bak files by default. Once I switched that off, things worked well.&lt;br /&gt;&lt;br /&gt;With regards to maintaining hard links to plug-ins generated from Visual Studio: make sure to use &lt;span style="font-style: italic;"&gt;Build&lt;/span&gt;, not &lt;span style="font-style: italic;"&gt;Rebuild &lt;/span&gt;- &lt;span style="font-style: italic;"&gt;Rebuild &lt;/span&gt;will destroy the original and break the link.&lt;br /&gt;&lt;br /&gt;So, that's it for now - hope this makes your life a bit easier!&lt;/original&gt;&lt;/destination&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1401434775260820755-6852532564100897277?l=rorohiko.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=wVwKk7T87Kc:cQa77jCQ7eA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=wVwKk7T87Kc:cQa77jCQ7eA:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=wVwKk7T87Kc:cQa77jCQ7eA:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=wVwKk7T87Kc:cQa77jCQ7eA:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?i=wVwKk7T87Kc:cQa77jCQ7eA:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=wVwKk7T87Kc:cQa77jCQ7eA:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=wVwKk7T87Kc:cQa77jCQ7eA:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?i=wVwKk7T87Kc:cQa77jCQ7eA:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=wVwKk7T87Kc:cQa77jCQ7eA:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?i=wVwKk7T87Kc:cQa77jCQ7eA:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=wVwKk7T87Kc:cQa77jCQ7eA:DN0H40_Ym5U"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?d=DN0H40_Ym5U" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rorohiko/~4/wVwKk7T87Kc" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-27T13:15:44.715-07:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://rorohiko.blogspot.com/2009/10/indesign-scripters-and-plug-in.html</feedburner:origLink></item><item><title>Display Workflow-Related Meta-Info  For Your Users From An InDesign Script</title><link>http://feedproxy.google.com/~r/Rorohiko/~3/bXhOuXIw0Xc/showing-user-some-workflow-related-info.html</link><category>APID ToolAssistant</category><category>VBScript</category><category>InDesign</category><category>metadata</category><category>ExtendScript</category><category>AppleScript</category><category>script</category><category>scripting</category><author>kris@rorohiko.com (Kris Coppieters)</author><pubDate>Wed, 14 Oct 2009 11:56:40 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-1401434775260820755.post-1494669579222709565</guid><description>&lt;div style="text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_BG3OWEhKX6c/StDkS1Hm1YI/AAAAAAAAAAw/sekNICAs_cI/s1600-h/Screen+shot+2009-10-05+at+6.11.36+PM.png"&gt;&lt;/a&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_BG3OWEhKX6c/Ss_y1f-51HI/AAAAAAAAAAo/LdEPrpn4f_c/s1600-h/Screen+shot+2009-10-10+at+3.34.06+PM.png" style="text-decoration: none;"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 289px; height: 217px;" src="http://4.bp.blogspot.com/_BG3OWEhKX6c/Ss_y1f-51HI/AAAAAAAAAAo/LdEPrpn4f_c/s320/Screen+shot+2009-10-10+at+3.34.06+PM.png" alt="" id="BLOGGER_PHOTO_ID_5390794279918097522" border="0" /&gt;&lt;/a&gt;&lt;div&gt;When developing workflow software around Adobe® InDesign® or Adobe® InDesign Server®, as a scripter, you often find yourself attaching 'meta-info' or metadata in some form or shape to various page elements in an InDesign document.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In this blog post, the samples should work with InDesign CS and above on Mac as well as on PC, and I'll use ExtendScript for InDesign for the scripts. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;But the information presented here can be applied just as well in AppleScript or VBScript. The syntax is slightly different, but it works equally well.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Meta-info would be any info that is not directly related to the page layout per se, but that needs to be associated with elements of the page layout. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Examples of meta-info you might like to attach to a page item would be things like invoice data, prices, product codes, file names, script labels, XML tags, user names, document history information, destinations, job ticket data...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In many cases, this meta-info can remain hidden from the end-user and not be displayed on the page layout at all - the data is typically picked up by various automated components of your workflow (scripts, applications, plug-ins...) and used to control processes and routing of info and documents.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;One of the most popular methods to attach meta-info to InDesign page items is to use the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;extractLabel&lt;/span&gt; and &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;insertLabel&lt;/span&gt; methods. These two essentially allow you to 'attach' any number of arbitrary strings to any page item, where you identify each of the strings you want to stash away with a key string.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For example, try the following script.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Open or create a document, select a page item and run the following script. (Be careful: the script has no error checking whatsoever, so it is not user-friendly. You need to select exactly one page item, and with the item selected, you need to run the script via the Scripts Palette).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;// Script1.js&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;var theItem = app.selection[0];&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;theItem.insertLabel("com.rorohiko.statusquo","Whatever you want tada tada whatever you need tada tada");&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Nothing apparent will seem to happen - that's OK. Now run the second script, while keeping the same page item selected:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;// Script2.js&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;var theItem = app.selection[0];&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;var theData = theItem.extractLabel("com.rorohiko.statusquo");&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;alert(theData);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This shows how you can attach a string to a page item. I do recommend that you use a globally unique string for the keys, for example, like I did, based on my reversed domain name. That helps ascertain that you don't accidentally use the same key as another scripter.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For example, if your domain name is &lt;i&gt;yourcompany.be&lt;/i&gt;, and you want to store, say, a user name, you should write something like:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;theItem.insertLabel("be.yourcompany.username","John");&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;instead of&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;theItem.insertLabel("username","John");&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The latter will also work, of course, but you always run the risk that your end user might try to run two scripts from two different developers.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Imagine she tries to use a script created by &lt;i&gt;yourcompany.be&lt;/i&gt; and also another script created by &lt;i&gt;rorohiko.com&lt;/i&gt;, and both scripts would use the same key &lt;i&gt;username&lt;/i&gt; for slightly different purposes. Lots of weirdness would result.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Better be safe than sorry - so if you use &lt;i&gt;be.yourcompany.username&lt;/i&gt;, and I use &lt;i&gt;com.rorohiko.username&lt;/i&gt; as the key to &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;insertLabel&lt;/span&gt; / &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;extractLabel&lt;/span&gt;, there will never be a conflict - are we cool on that?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The string you store in the keyed location can be pretty much anything - I often store a very looong string, for example, with carriage returns separating individual records, and tabs separating individual columns, and then use .split to convert the string in to a table.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;const kMyDataKey = "com.rorohiko.keyforimportantdata";&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new',serif;"&gt;//... more code ...&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new',serif;"&gt;// Little table of data with columns separated by tabs&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new',serif;"&gt;// and lines separated by carriage returns&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new',serif;"&gt;// 12 13 Kris&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new',serif;"&gt;// 15 17 John&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;var myImportantData = "12\t13\tKris\r15\t17\tJohn\r";&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;theItem.insertLabel(kMyDataKey,myImportantData);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;//... more code ...&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;var theData = theItem.extractLabel(kMyDataKey);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;theData = theData.split("\r");&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;for (var recordIdx = 0; recordIdx &lt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;  theData[recordIdx] = theData[recordIdx].split("\t");&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;//... more code ...&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Or you could encode the data you want to stash into a big XML formatted string - that works really well too - something like:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;const kMyDataKey = "com.rorohiko.thecoolKeyForXMLData";&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;//... more code ...&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;var myImportantData = "";&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;myImportantData += "&amp;lt;data&amp;gt;&lt;data&gt;"&lt;/data&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;myImportantData += "&amp;lt;record&amp;gt;"&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;myImportantData += "&amp;lt;x&amp;gt;&lt;x&gt;12&amp;lt;/x&amp;gt;&amp;lt;y&amp;gt;&lt;y&gt;13&amp;lt;/y&amp;gt;&amp;lt;name&amp;gt;&lt;name&gt;Kris&amp;lt;/name&amp;gt;";&lt;/name&gt;&lt;/y&gt;&lt;/x&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;myImportantData += "&amp;lt;/record&amp;gt;"&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;myImportantData += "&amp;lt;record&amp;gt;"&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;myImportantData += "&amp;lt;x&amp;gt;&lt;x&gt;15&amp;lt;/x&amp;gt;&amp;lt;y&amp;gt;&lt;y&gt;17&amp;lt;/y&amp;gt;&amp;lt;name&amp;gt;&lt;name&gt;John&amp;lt;/name&amp;gt;";&lt;/name&gt;&lt;/y&gt;&lt;/x&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new',serif;"&gt;myImportantData += "&amp;lt;/record&amp;gt;"&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new',serif;"&gt;myImportantData += "&amp;lt;/data&amp;gt;&lt;data&gt;"&lt;/data&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new',serif;"&gt;theItem.insertLabel(kMyDataKey,myImportantData);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;//... more code ...&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;var theData = theItem.extractLabel(kMyDataKey);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;// Use the built-in XML parser to parse the XML data back into its components&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;//... more code ...&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Or any other scheme you can come up with to convert the data you want to store into a string- you can do things like ASCIIEncode or ASCII85 the data if you want to store binary info in a pure ASCII string - your imagination is the limit.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now, what if you wanted some of this data to be visible to the end-user? &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For example, the end-user could use one of your scripts to tag individual page items, maybe to let your automated workflow 'see' where it needs to insert a header and where it needs to put an image, and so on.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Wouldn't it be great if you could give the user some visual feedback in this regard?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;That's where our APID ToolAssistant comes in. APID ToolAssistant was conceived as a 'scripters toolkit' and it offers a whole range of functionality that could help the serious scripter.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You might have heard about APID ToolAssistant, because it offers a very 'fine grained' event model that allows scripts to be triggered by user interaction with the document - but APID ToolAssistant has a lot more to offer than just some event-driven facilities.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;One of the coolest features in the APID ToolAssistant toolkit is that it offers the scripter a way to display any 'meta-info' next to a page item. To display this meta-info, APID ToolAssistant can add little, non-printing 'labels' (also known as &lt;i&gt;adornments&lt;/i&gt;) to any page item, and in those labels, you can display anything you like: some text, or a PNG image like a logo or an icon, all under the control of your script.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;These adornments are not page items - they are instead very similar in nature to the selection handles and the overset text indicator on page item frames. They are nothing more than visual cues for the user, and they are not visible in the printed end-result.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The way APID ToolAssistant works its magic is by adding some new methods and attributes to the InDesign object model. There is a pair of methods called &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;setDataStore&lt;/span&gt; / &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;getDataStore&lt;/span&gt; which behave very similar in many respects to how the built-in &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;insertLabel&lt;/span&gt; / &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;extractLabel&lt;/span&gt; work - i.e. you store data identified by a unique key.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;But there's a twist - some of the unique keys have a special meaning - they are 'magical'. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If a key starts with &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;$ADORNMENT_&lt;/span&gt; and ends with &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;$&lt;/span&gt;, it tells APID ToolAssistant the stored data is something that has to be interpreted as content for a little info-label.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Install APID ToolAssistant 1.0.47 or higher (you can download it from &lt;a href="http://www.rorohiko.com/apidtoolassistant"&gt;http://www.rorohiko.com/apidtoolassistant&lt;/a&gt; ), and enter the following script:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;// Script3.js&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;var theItem = app.selection[0];&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;theItem.setDataStore("$ADORNMENT_com.rorohiko.sample$","Hello World");&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Just like with the first sample scripts you need to select a single page item, and then run the script.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Is that cool or what? (If your APID ToolAssistant has been installed for a while, it might have reverted to unlicensed mode, in which case you'd see 'DEMO: Hello World' in the little info-label).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now, this is only a simple example - instead of a simple string "Hello World" you can actually provide an array with data to &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;setDataStore&lt;/span&gt;, and through various parameter values ask APID ToolAssistant to display the label on the left, right or bottom sides of the frame.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Or you can ask it to change the background color. Or for really fancy stuff, you can display a PNG image instead of text. The possibilities are endless.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To get some ideas about what you could do with this functionality, have a look at what I've done with our FrameReporter tool at &lt;a href="http://www.rorohiko.com/framereporter"&gt;http://www.rorohiko.com/framereporter&lt;/a&gt; . FrameReporter is really not much more than a very thin layer of code on top of APID ToolAssistant.&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: rgb(0, 0, 238);"&gt;&lt;img src="http://4.bp.blogspot.com/_BG3OWEhKX6c/StDkS1Hm1YI/AAAAAAAAAAw/sekNICAs_cI/s320/Screen+shot+2009-10-05+at+6.11.36+PM.png" alt="" id="BLOGGER_PHOTO_ID_5391059766110246274" style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 244px;" border="0" /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;For more detailed info, you need to look at the information provided in the Active Page Items Developer toolkit - &lt;a href="http://www.rorohiko.com/activepageitemsdeveloper"&gt;http://www.rorohiko.com/activepageitemsdeveloper&lt;/a&gt; .&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The necessary documentation is included in the free demo download - you don't need to purchase the toolkit if all you want to do is use this 'meta-info-label' feature. Check the reference manual to find out about all the variations of the adornment features.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So, keep in mind - if you want to show meta-info to an end-user, all you need is a US$25 license for APID ToolAssistant (to get rid of those 'DEMO:' prefixes added by the unlicensed version), and you can script away!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;More info can also be found here:&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.rorohiko.com/wordpress/2008/10/15/how-to-add-indesign-page-item-adornments-using-scripting/"&gt;http://www.rorohiko.com/wordpress/2008/10/15/how-to-add-indesign-page-item-adornments-using-scripting/&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1401434775260820755-1494669579222709565?l=rorohiko.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=bXhOuXIw0Xc:LSvVOncorzU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=bXhOuXIw0Xc:LSvVOncorzU:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=bXhOuXIw0Xc:LSvVOncorzU:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=bXhOuXIw0Xc:LSvVOncorzU:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?i=bXhOuXIw0Xc:LSvVOncorzU:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=bXhOuXIw0Xc:LSvVOncorzU:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=bXhOuXIw0Xc:LSvVOncorzU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?i=bXhOuXIw0Xc:LSvVOncorzU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=bXhOuXIw0Xc:LSvVOncorzU:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?i=bXhOuXIw0Xc:LSvVOncorzU:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=bXhOuXIw0Xc:LSvVOncorzU:DN0H40_Ym5U"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?d=DN0H40_Ym5U" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rorohiko/~4/bXhOuXIw0Xc" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-14T11:56:40.575-07:00</app:edited><media:thumbnail url="http://4.bp.blogspot.com/_BG3OWEhKX6c/Ss_y1f-51HI/AAAAAAAAAAo/LdEPrpn4f_c/s72-c/Screen+shot+2009-10-10+at+3.34.06+PM.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://rorohiko.blogspot.com/2009/10/showing-user-some-workflow-related-info.html</feedburner:origLink></item><item><title>Apple Mail and the Drafts folder</title><link>http://feedproxy.google.com/~r/Rorohiko/~3/XZqqvHuyR8o/apple-mail-and-drafts-folder.html</link><author>kris@rorohiko.com (Kris Coppieters)</author><pubDate>Tue, 11 Aug 2009 23:21:57 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-1401434775260820755.post-4084201307090529618</guid><description>I use Apple Mail, and generally, it does work well. However, there's one thing that annoys me: if you don't have any 'pending' draft e-mails, the Drafts mail folder is invisible and cannot be seen in the mail window. &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;That seems like a non-issue, but I like to use the Drafts folder for 'repetitive' e-mail. I sometimes send out a similar e-mail to two or three people, and I like to option-drag previously sent e-mail from the Sent mail folder back to the Drafts folder to make a modifiable copy.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;What I used to do in previous versions of Apple Mail was the following:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;1) Type in an e-mail. Hit 'Send'.&lt;/div&gt;&lt;div&gt;2) Open the 'Sent' folder in Apple Mail and Option-Drag the e-mail I just sent to the Drafts folder. That makes a copy of the e-mail, and makes it available as a draft.&lt;/div&gt;&lt;div&gt;3) Double-click the draft in the Drafts folder, and adjust it to suit the next addressee; hit 'Send'.&lt;/div&gt;&lt;div&gt;4) Go back to step 2 as needed.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Because in more recent versions of Apple Mail, the Drafts folder becomes invisible if it is empty, I used the following clumsy workaround:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;0) Create an empty, dummy e-mail and hit 'Save as Draft'. That puts something in the Drafts folder, and I can start using my previous trick (option-drag sent e-mail into Drafts to make a modifiable copy). Go to step 1) above.&lt;/div&gt;&lt;div&gt;...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;That works OK, but the dummy e-mail is blank, and you end up with a blank e-mail in the Drafts folder - I don't really like that.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So, finally my current workaround is to create a single, non-blank e-mail in the Drafts folder, and leave it there for eternity. It's not perfect, but I can live with that.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_BG3OWEhKX6c/SoJeq9dz9EI/AAAAAAAAAAY/isKesfw82-I/s1600-h/Picture+5.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 214px;" src="http://3.bp.blogspot.com/_BG3OWEhKX6c/SoJeq9dz9EI/AAAAAAAAAAY/isKesfw82-I/s320/Picture+5.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5368957797926171714" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;The Drafts folder now has a permanent mail in it.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_BG3OWEhKX6c/SoJezYN6bUI/AAAAAAAAAAg/YJELjUjvQrU/s1600-h/Picture+6.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 78px;" src="http://4.bp.blogspot.com/_BG3OWEhKX6c/SoJezYN6bUI/AAAAAAAAAAg/YJELjUjvQrU/s320/Picture+6.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5368957942546197826" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;Not the greatest trick in the world, but it made my life a little bit easier, so I thought I'd share it.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Cheers,&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Kris&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1401434775260820755-4084201307090529618?l=rorohiko.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=XZqqvHuyR8o:n1fmAQCf2Aw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=XZqqvHuyR8o:n1fmAQCf2Aw:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=XZqqvHuyR8o:n1fmAQCf2Aw:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=XZqqvHuyR8o:n1fmAQCf2Aw:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?i=XZqqvHuyR8o:n1fmAQCf2Aw:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=XZqqvHuyR8o:n1fmAQCf2Aw:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=XZqqvHuyR8o:n1fmAQCf2Aw:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?i=XZqqvHuyR8o:n1fmAQCf2Aw:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=XZqqvHuyR8o:n1fmAQCf2Aw:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?i=XZqqvHuyR8o:n1fmAQCf2Aw:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=XZqqvHuyR8o:n1fmAQCf2Aw:DN0H40_Ym5U"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?d=DN0H40_Ym5U" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rorohiko/~4/XZqqvHuyR8o" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-11T23:21:57.268-07:00</app:edited><media:thumbnail url="http://3.bp.blogspot.com/_BG3OWEhKX6c/SoJeq9dz9EI/AAAAAAAAAAY/isKesfw82-I/s72-c/Picture+5.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://rorohiko.blogspot.com/2009/08/apple-mail-and-drafts-folder.html</feedburner:origLink></item><item><title>Little Known Facts About InDesign Plug-Ins - There is More To It Than Meets The Eye</title><link>http://feedproxy.google.com/~r/Rorohiko/~3/yBmavKmja_M/little-known-facts-about-indesign-plug.html</link><author>kris@rorohiko.com (Kris Coppieters)</author><pubDate>Tue, 28 Jul 2009 01:41:52 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-1401434775260820755.post-4194175346316567293</guid><description>&lt;span style="font-style: italic;"&gt;Installing&lt;/span&gt; a plug-in for Adobe InDesign is normally fairly straightforward.&lt;br /&gt;&lt;br /&gt;• Quit or exit out of InDesign.&lt;br /&gt;• Navigate to the folder that contains the InDesign application file.&lt;br /&gt;• Find the folder called 'Plug-Ins'.&lt;br /&gt;• For neatness, create a subfolder inside 'Plug-Ins' - e.g. 'Third Party Plug-Ins'. Drag the plug-in icons (and possibly any associated files) into that subfolder.&lt;br /&gt;• Relaunch InDesign&lt;br /&gt;&lt;br /&gt;That's fairly easy.&lt;br /&gt;&lt;br /&gt;But when it comes to &lt;span style="font-style: italic;"&gt;upgrading&lt;/span&gt; things might become a bit more complex.&lt;br /&gt;&lt;br /&gt;In short, you might want to first remove the previous version of the plug-in, then start and immediately exit InDesign, and only then install the updated version.&lt;br /&gt;&lt;br /&gt;In other words - perform an 'empty' start/stop of InDesign before installing the updated plug-in.&lt;br /&gt;&lt;br /&gt;Whether this is really necessary depends on the plug-in - most plug-ins won't need this. But if you're battling a mysterious problem, this is worth a try.&lt;br /&gt;&lt;br /&gt;Here's what might happen.&lt;br /&gt;&lt;br /&gt;Each time you launch InDesign it will scan the Plug-Ins folder and its subfolders, looking for any new plug-ins. If it cannot find any new plug-ins, nothing special happens - we have a bog-standard, normal InDesign launch.&lt;br /&gt;&lt;br /&gt;But when InDesign &lt;span style="font-style: italic;"&gt;does&lt;/span&gt; find a new plug-in - a plug-in it has not 'seen' before, things are different, and the launch takes longer than normal.&lt;br /&gt;&lt;br /&gt;Most people won't notice it - the difference in launch time is not very large. If you're really observant, you'll also see some extra messages flash by in the InDesign splash screen.&lt;br /&gt;&lt;br /&gt;Behind the curtain, InDesign is analyzing the new plug-in and extracting information from it.&lt;br /&gt;&lt;br /&gt;For example, information on how the new plug-in can be scripted, and information about the wording on the dialogs and palettes the plug-in can display.&lt;br /&gt;&lt;br /&gt;A lot of this extracted information is then stashed away by InDesign for 'later reference' - this to avoid having to re-analyze the same plug-in on each re-start.&lt;br /&gt;&lt;br /&gt;So, the next time InDesign launches, it again checks for new plug-ins. If no new stuff can be found, it relies on its information stash (also known as 'cache'), and it can launch faster, because it does not have to spend time analyzing any plug-ins.&lt;br /&gt;&lt;br /&gt;This 'trick' is called 'caching' - caches are used in many situations, to avoid needless effort to re-obtain data that has been obtained before.&lt;br /&gt;&lt;br /&gt;For example, your web browser does it too - the first time ever you access a particular web page, it will be a tad sluggish, especially when there are a lot of graphics. Navigate to that same page a little bit later, and in most cases it will come up a lot faster.&lt;br /&gt;&lt;br /&gt;The browser has &lt;span style="font-style: italic;"&gt;cached&lt;/span&gt; the page content and instead of accessing the web site far, far away, it is showing you a copy of the page it had cached in its local web file cache. The web page comes straight off your hard disk, which is a lot faster than pulling it through the internet.&lt;br /&gt;&lt;br /&gt;So, keep in mind: to improve launch times,  InDesign &lt;span style="font-style: italic;"&gt;caches&lt;/span&gt; a lot of information that is normally stored inside of the plug-in files.&lt;br /&gt;&lt;br /&gt;Now suppose you have a plug-in installed. It's working fairly well, but there are some issues.&lt;br /&gt;&lt;br /&gt;Some time later the software developer releases an updated version of the plug-in, which should fix the issues. You download the new version, and overwrite the old version with it.&lt;br /&gt;&lt;br /&gt;Done? Is it that easy? Not always!&lt;br /&gt;&lt;br /&gt;The problem is that InDesign might not scan the updated plug-in: for all it knows, it 'saw' file 'xyz.pln' before, and it still sees 'xyz.pln' - InDesign might feel no urge to re-scan 'xyz.pln'.&lt;br /&gt;&lt;br /&gt;As a result, InDesign might be relying on the outdated info from the previous version of the plug-in that it has in its information stash.&lt;br /&gt;&lt;br /&gt;And weird things might start to happen - things mysteriously don't work well on some computers, but work fine on others, that kind of stuff.&lt;br /&gt;&lt;br /&gt;Morale: it might be a good idea to force InDesign to re-scan the new plug-in. To achieve that, you can use the following procedure:&lt;br /&gt;&lt;br /&gt;0) Exit out of InDesign&lt;br /&gt;1) Completely remove the plug-in you're about to upgrade&lt;br /&gt;2) Launch InDesign (without the plug-in installed). It will notice the plug-in is missing, and it will erase any cached data it had extracted from it.&lt;br /&gt;3) Exit out of InDesign&lt;br /&gt;4) Install the updated version of the plug-in&lt;br /&gt;5) Launch InDesign (with the updated plug-in installed). It will see the 'new' plug-in and re-scan it - so the cached data is now up-to-date.&lt;br /&gt;&lt;br /&gt;Keep in mind: this info is quite general, and might not apply to your situation. But if all else fails - give it a go!&lt;br /&gt;&lt;br /&gt;Cheers,&lt;br /&gt;&lt;br /&gt;Kris&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1401434775260820755-4194175346316567293?l=rorohiko.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=yBmavKmja_M:4kPcbx7c_1w:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=yBmavKmja_M:4kPcbx7c_1w:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=yBmavKmja_M:4kPcbx7c_1w:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=yBmavKmja_M:4kPcbx7c_1w:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?i=yBmavKmja_M:4kPcbx7c_1w:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=yBmavKmja_M:4kPcbx7c_1w:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=yBmavKmja_M:4kPcbx7c_1w:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?i=yBmavKmja_M:4kPcbx7c_1w:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=yBmavKmja_M:4kPcbx7c_1w:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?i=yBmavKmja_M:4kPcbx7c_1w:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=yBmavKmja_M:4kPcbx7c_1w:DN0H40_Ym5U"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?d=DN0H40_Ym5U" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rorohiko/~4/yBmavKmja_M" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-28T01:41:52.952-07:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://rorohiko.blogspot.com/2009/07/little-known-facts-about-indesign-plug.html</feedburner:origLink></item><item><title>Some baffling behavior in InDesign CS3 scripts explained - beware of relative object references</title><link>http://feedproxy.google.com/~r/Rorohiko/~3/cFDImI2udMQ/some-baffling-behavior-in-indesign-cs3.html</link><author>kris@rorohiko.com (Kris Coppieters)</author><pubDate>Tue, 21 Jul 2009 14:56:47 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-1401434775260820755.post-8353677952511523075</guid><description>Lesson learned: be careful with references to page items in InDesign ExtendScript CS3 - you might be referring to the wrong object!&lt;br /&gt;&lt;br /&gt;The issue described below seems fixed in InDesign ExtendScript CS4 - but if you need to support CS3, you should be aware of it.&lt;br /&gt;&lt;br /&gt;Look at this code snippet:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;var itemB = app.activeDocument.pageItems.item(1);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;alert(itemB.id);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;... do some stuff that does not affect itemB ...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;alert(itemB.id);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;What would you expect to happen? You'd expect to see the same id value displayed in two alerts, right?&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;itemB&lt;/span&gt; refers to a particular page item, and should continue to do so. Turns out that is not the case in InDesign CS3.&lt;br /&gt;&lt;br /&gt;Try this:&lt;br /&gt;&lt;br /&gt;Create a new document, and create three rectangular frames on the first page.&lt;br /&gt;&lt;br /&gt;Create the following script:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;var itemA = app.activeDocument.pageItems.item(0);&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;var itemB = app.activeDocument.pageItems.item(1);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;var itemC = app.activeDocument.pageItems.item(2);&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;alert(itemB.id);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;itemA.remove();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;alert(itemB.id);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;You would expect &lt;span style="font-family:courier new;"&gt;itemB&lt;/span&gt; not to be affected by removing &lt;span style="font-family:courier new;"&gt;itemA&lt;/span&gt; - but it is! Run the script and you'll get two different &lt;span style="font-family:courier new;"&gt;id&lt;/span&gt; values displayed in the dialog.&lt;br /&gt;&lt;br /&gt;I don't &lt;span style="font-style: italic;"&gt;really&lt;/span&gt; know for sure what is going on but I have a theory - it looks like &lt;span style="font-family:courier new;"&gt;itemB&lt;/span&gt; has 'become' &lt;span style="font-family:courier new;"&gt;itemC&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;I suspect that InDesign CS3 does not really keep a 'hard' reference to any particular item in the &lt;span style="font-family:courier new;"&gt;itemB&lt;/span&gt; variable - instead it has what I'd call a 'relative reference'.&lt;br /&gt;&lt;br /&gt;In other words, &lt;span style="font-family:courier new;"&gt;itemB&lt;/span&gt; is &lt;span style="font-style: italic;"&gt;not&lt;/span&gt; fixed - it always remains equivalent to '&lt;span style="font-family:courier new;"&gt;app.activeDocument.pageItems.item(1)' &lt;/span&gt;- and if the page item list changes 'underneath', then &lt;span style="font-family:courier new;"&gt;itemB&lt;/span&gt; suddenly will refer to another item.&lt;br /&gt;&lt;br /&gt;After the &lt;span style="font-family:courier new;"&gt;remove()&lt;/span&gt;, the page item list of the document has changed - the item at index 1 is now a different item. So the variable &lt;span style="font-family:courier new;"&gt;itemB&lt;/span&gt; suddenly refers to a different item.&lt;br /&gt;&lt;br /&gt;Can we create hard references that don't suffer from this issue? Turns out we can - so there is a solution.&lt;br /&gt;&lt;br /&gt;Change the script to read:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;var itemA = app.activeDocument.pageItems.item(0);&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;var itemB = app.activeDocument.pageItems.item(1);&lt;/span&gt;&lt;br /&gt; &lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;var itemC = app.activeDocument.pageItems.item(2);&lt;br /&gt;itemB = app.activeDocument.pageItems.itemByID(itemB.id);&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;alert(itemB.id);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;itemA.remove();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;alert(itemB.id);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;That looks like a do-nothing: replace the reference to &lt;span style="font-family:courier new;"&gt;itemB&lt;/span&gt; with another reference to &lt;span style="font-family:courier new;"&gt;itemB&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;But internally, InDesign will now refer to 'the item with id=1234' (assuming &lt;span style="font-family:courier new;"&gt;itemB&lt;/span&gt; had an id equal to 1234). &lt;span style="font-family:courier new;"&gt;itemB.id&lt;/span&gt; uniquely identifies &lt;span style="font-family:courier new;"&gt;itemB&lt;/span&gt;, and it is not affected by items being added or removed from the page item list.&lt;br /&gt;&lt;br /&gt;So this updated script works as expected - we see the same id displayed before and after the remove.&lt;br /&gt;&lt;br /&gt;We can write a small helper function for this:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;function FreezeReference(theItem)&lt;br /&gt;{&lt;br /&gt; // Harbs improved my original attempt by&lt;br /&gt; // appending .getElements()[0] - thanks&lt;br /&gt; // Harbs!&lt;br /&gt; return theItem.parent.pageItems.itemByID(theItem.id).getElements()[0];&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;var itemA = app.activeDocument.pageItems.item(0);&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;var itemB = &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;FreezeReference(&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;app.activeDocument.pageItems.item(1));&lt;/span&gt;&lt;br /&gt; &lt;span style="font-family:courier new;"&gt;var itemC = app.activeDocument.pageItems.item(2);&lt;br /&gt;itemB = app.activeDocument.pageItems.itemByID(itemB.id);&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;alert(itemB.id);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;itemA.remove();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;alert(itemB.id);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This also works as expected.&lt;br /&gt;&lt;br /&gt;Uncovering this issue was not as straightforward as it might seem - at first, it looked like I was struggling with a bug in our &lt;a href="http://www.rorohiko.com/activepageitemsdeveloper"&gt;APIDToolAssistant&lt;/a&gt; plug-in: Harbs (&lt;a href="http://www.in-tools.com/"&gt;www.in-tools.com&lt;/a&gt;) who is an advanced user of APIDToolAssistant reported some issues with the 'move into' function provided by APIDToolAssistant.&lt;br /&gt;&lt;br /&gt;This particular ExtendScript enhancement allows you to move one page item into another very quickly; much faster than could be achieved with pure scripting - you'd do something like this:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;// Some 'magic' numbers - C++ meets ExtendScript&lt;br /&gt;const IID_IACTIVEPAGEITEMSCRIPTUTILITIESEXTENSION = 0x90B6C;&lt;br /&gt;const kOpCode_MoveInto = 10016;&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;function MoveItemIntoItem(newParent,newChild)&lt;br /&gt;{&lt;br /&gt; app.callExtension(&lt;br /&gt;   IID_IACTIVEPAGEITEMSCRIPTUTILITIESEXTENSION,&lt;br /&gt;   kOpCode_MoveInto,&lt;br /&gt;   newParent,&lt;br /&gt;   newChild);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;var itemA = app.activeDocument.pageItems.item(0);&lt;br /&gt;var itemB = app.activeDocument.pageItems.item(1);&lt;br /&gt;var itemC = app.activeDocument.pageItems.item(2);&lt;br /&gt;alert(itemB.id);&lt;br /&gt;MoveItemIntoItem(itemA,itemB);&lt;br /&gt;alert(itemB.id);&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;app.callExension()&lt;/span&gt; 'calls into' the APIDToolAssistant plug-in to perform the move.&lt;br /&gt;&lt;br /&gt;He noticed that he got invalid object references after calling this function in CS3.&lt;br /&gt;&lt;br /&gt;Turned out &lt;a href="http://www.rorohiko.com/activepageitemsdeveloper"&gt;APIDToolAssistant&lt;/a&gt; was not the culprit - after some digging I finally figured out what was going on.&lt;br /&gt;&lt;br /&gt;Hope this is useful!&lt;br /&gt;&lt;br /&gt;Cheers,&lt;br /&gt;&lt;br /&gt;Kris&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1401434775260820755-8353677952511523075?l=rorohiko.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=cFDImI2udMQ:2ukHN0IVCkM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=cFDImI2udMQ:2ukHN0IVCkM:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=cFDImI2udMQ:2ukHN0IVCkM:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=cFDImI2udMQ:2ukHN0IVCkM:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?i=cFDImI2udMQ:2ukHN0IVCkM:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=cFDImI2udMQ:2ukHN0IVCkM:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=cFDImI2udMQ:2ukHN0IVCkM:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?i=cFDImI2udMQ:2ukHN0IVCkM:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=cFDImI2udMQ:2ukHN0IVCkM:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?i=cFDImI2udMQ:2ukHN0IVCkM:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=cFDImI2udMQ:2ukHN0IVCkM:DN0H40_Ym5U"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?d=DN0H40_Ym5U" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rorohiko/~4/cFDImI2udMQ" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-21T14:56:47.499-07:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://rorohiko.blogspot.com/2009/07/some-baffling-behavior-in-indesign-cs3.html</feedburner:origLink></item><item><title>VMware Fusion and TimeMachine</title><link>http://feedproxy.google.com/~r/Rorohiko/~3/dwJEDrkfTq0/vmware-fusion-and-timemachine.html</link><author>kris@rorohiko.com (Kris Coppieters)</author><pubDate>Thu, 16 Jul 2009 21:36:54 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-1401434775260820755.post-5809501506886444504</guid><description>Been a while since I blogged; swamped in work. &lt;br /&gt;&lt;br /&gt;This quick post to share a solution I found on Mac OS X to make VMware Fusion (or Parallels) and Apple's Time Machine backup work better together.&lt;br /&gt;&lt;br /&gt;I use a fair amount of virtual Windows and Linux machines, and these tend to be primarily stored in large virtual hard disk files - 40GB, 60GB,... pretty massive. &lt;br /&gt;&lt;br /&gt;Because Time Machine finds and copies any modified file, and the mere act of running the virtual Windows machines caused these large files to be marked as 'modified', I was faced with endless copies of massive virtual hard disk files to my Time Machine hard drive. &lt;br /&gt;&lt;br /&gt;Figuratively speaking, a one-byte change in one of those massive Windows virtual hard disk files would cause a 60GB copy operation - which also indirectly forced older backup files to be erased from the Time Machine drive to make room for these behemoths.&lt;br /&gt;&lt;br /&gt;Initially, I put all my virtual machines in a single folder, and explicitly excluded that folder from the Time Machine backup - not a good solution, but at least, my backup drive was not swamped with those big files.&lt;br /&gt;&lt;br /&gt;But then, a few days ago it dawned on me - I could have my cake and eat it too! &lt;br /&gt;&lt;br /&gt;The solution is to use the 'snapshot' feature of VMware (Parallels also has it) - you can make a snapshot of a virtual machine, so you can always 'undo' whatever happened to that virtual machine since the last snapshot.&lt;br /&gt;&lt;br /&gt;The way VMware handles this is by 'freezing' the underlying virtual hard disk, and storing any changes made since the snapshot to the frozen hard disk in separate files.&lt;br /&gt;&lt;br /&gt;And that's the solution: I first make sure my virtual machine is in a useful, stable state, and then I make a snapshot (I call it 'Base'). &lt;br /&gt;&lt;br /&gt;That effectively 'locks' the massive many-GB virtual drive - so running VMware does not cause it to be modified any more, and any changes from then on are kept in a bunch of much smaller snapshot files.&lt;br /&gt;&lt;br /&gt;Time Machine now makes a copy of my 'frozen' many-GB virtual drive once, and from then on only backs up the changes that are kept in the snapshot files - which results in a much smaller backup set.&lt;br /&gt;&lt;br /&gt;After a while, when the snapshot file size grows to many GB in size, I make a new snapshot, and delete the old snapshot. That 'merges' all changes that occurred 'between' the two snapshots into the main virtual drive, and starts with a fresh slate. &lt;br /&gt;&lt;br /&gt;After I do that, Time Machine backs up the behemoth once again, and from then again only backs up the changes in the new set of snapshot files.&lt;br /&gt;&lt;br /&gt;I now have a good backup of my virtual machines again without having to jump through hoops! &lt;br /&gt;&lt;br /&gt;Cheers,&lt;br /&gt;&lt;br /&gt;Kris&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1401434775260820755-5809501506886444504?l=rorohiko.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=dwJEDrkfTq0:LaCDvugZCeo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=dwJEDrkfTq0:LaCDvugZCeo:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=dwJEDrkfTq0:LaCDvugZCeo:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=dwJEDrkfTq0:LaCDvugZCeo:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?i=dwJEDrkfTq0:LaCDvugZCeo:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=dwJEDrkfTq0:LaCDvugZCeo:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=dwJEDrkfTq0:LaCDvugZCeo:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?i=dwJEDrkfTq0:LaCDvugZCeo:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=dwJEDrkfTq0:LaCDvugZCeo:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?i=dwJEDrkfTq0:LaCDvugZCeo:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=dwJEDrkfTq0:LaCDvugZCeo:DN0H40_Ym5U"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?d=DN0H40_Ym5U" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rorohiko/~4/dwJEDrkfTq0" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-16T21:36:54.844-07:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://rorohiko.blogspot.com/2009/07/vmware-fusion-and-timemachine.html</feedburner:origLink></item><item><title>May 11-15 InDesign Developer Training Sessions</title><link>http://feedproxy.google.com/~r/Rorohiko/~3/UQB7GBeACiI/may-11-15-indesign-developer-training.html</link><author>kris@rorohiko.com (Kris Coppieters)</author><pubDate>Sun, 22 Mar 2009 14:04:10 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-1401434775260820755.post-4961139259725198288</guid><description>&lt;div class="entry"&gt;       &lt;p&gt;If you’re involved in automation around the Adobe Creative Suite, you need to mark the week of May 11 - 15, 2009 on your calendar - there’s another Creative Suite Developer Summit coming up in Seattle, on the Adobe Fremont Campus&lt;/p&gt; &lt;p&gt;We’re running two training sessions this year - click the lines below for more info:&lt;/p&gt; &lt;p&gt;On May 11:&lt;a href="http://www.rorohiko.com/wordpress/indesign-sdk-training-may-11th-seattle-adobe-fremont-campus/" target="_blank"&gt; InDesign Plugin Development Workshop - Getting Started With The InDesign SDK&lt;/a&gt;&lt;/p&gt; &lt;p&gt;On May 15:&lt;a href="http://www.rorohiko.com/wordpress/feature-development-for-indesign-using-extendscript-may-15th-seattle-adobe-fremont-campus/" target="_blank"&gt; Feature Development for InDesign Using ExtendScript&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Both workshops are limited to 12 seats, which will be allocated on a first come, first served basis - so don’t delay booking.&lt;/p&gt; &lt;p&gt;More about the Adobe Creative Suite Developer Conference can be found here:&lt;/p&gt;&lt;p&gt;&lt;a href="http://niemannross.host.adobe.com/2009csbuDeveloperSummit/" target="_blank"&gt; &lt;br /&gt;http://niemannross.host.adobe.com/2009csbuDeveloperSummit/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;As space is limited to 12 attendees per course, you should make sure you enroll early. There's also a 10% price reduction for people who enroll in both courses before April, 15.&lt;/p&gt;&lt;p&gt;Cheers,&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Kris&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1401434775260820755-4961139259725198288?l=rorohiko.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=UQB7GBeACiI:UODiIurTo0Q:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=UQB7GBeACiI:UODiIurTo0Q:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=UQB7GBeACiI:UODiIurTo0Q:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=UQB7GBeACiI:UODiIurTo0Q:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?i=UQB7GBeACiI:UODiIurTo0Q:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=UQB7GBeACiI:UODiIurTo0Q:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=UQB7GBeACiI:UODiIurTo0Q:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?i=UQB7GBeACiI:UODiIurTo0Q:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=UQB7GBeACiI:UODiIurTo0Q:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?i=UQB7GBeACiI:UODiIurTo0Q:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Rorohiko?a=UQB7GBeACiI:UODiIurTo0Q:DN0H40_Ym5U"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rorohiko?d=DN0H40_Ym5U" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rorohiko/~4/UQB7GBeACiI" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-22T14:04:10.609-07:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://rorohiko.blogspot.com/2009/03/may-11-15-indesign-developer-training.html</feedburner:origLink></item><item><title>New Cookbook Blog</title><link>http://feedproxy.google.com/~r/Rorohiko/~3/n3EhYwEI6uM/new-cookbook-blog.html</link><author>kris@rorohiko.com (Kris Coppieters)</author><pubDate>Thu, 16 Oct 2008 12:46:53 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-1401434775260820755.post-8426113658622443468</guid><description>I've started a new blog which will be mainly like a 'cookbook' for Adobe Creative Suite scripters - how-to articles that show how to write much more powerful scripts.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.rorohiko.com/wordpress"&gt;http://www.rorohiko.com/wordpress&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The first entry in the blog is up - it's about how you can 'attach' little icons or labels to the four sides of page items as a means of feedback to the user of your scripts. The sample script adds a little floating label with the word count to each text frame - so the user can see the amount of words in each text frame in the blink of an eye.&lt;br /&gt;&lt;br /&gt;Check it out!&lt;br /&gt;&lt;br /&gt;Cheers,&lt;br /&gt;&lt;br /&gt;Kris&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1401434775260820755-8426113658622443468?l=rorohiko.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=wgOqoiDt"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=7w5bFma5"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=42" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=VUCrOsmA"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=CXIjU5CG"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?i=CXIjU5CG" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=VUFLH4eX"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=AWIr88eY"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?i=AWIr88eY" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=s8NQg0Hg"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?i=s8NQg0Hg" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=3ulOU6Yl"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=134" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rorohiko/~4/n3EhYwEI6uM" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2008-10-16T12:46:53.415-07:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://rorohiko.blogspot.com/2008/10/new-cookbook-blog.html</feedburner:origLink></item><item><title>Lightning Brain Podcast: Click here to listen to "Using State Machines: Web Access From Adobe InDesign CS3 ExtendScript"</title><link>http://feedproxy.google.com/~r/Rorohiko/~3/LudYNykZzxQ/lightning-brain-podcast-click-here-to.html</link><author>kris@rorohiko.com (Kris Coppieters)</author><pubDate>Sat, 12 Jul 2008 00:37:13 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-1401434775260820755.post-7418105582007685987</guid><description>Sample files for this podcast can be downloaded from:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.rorohiko.com/podcast/geturl.zip"&gt;http://www.rorohiko.com/podcast/geturl.zip&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This podcast will explain how you can query web services from within InDesign CS3 ExtendScript. No need for plug-ins, external libraries - just Adobe InDesign ExtendScript, pure and simple.&lt;br /&gt;&lt;br /&gt;I'll also present some useful routines I wrote, called &lt;span style="font-style:italic;"&gt;GetURL()&lt;/span&gt; and &lt;span style="font-style:italic;"&gt;ParseURL()&lt;/span&gt;. &lt;span style="font-style:italic;"&gt;GetURL()&lt;/span&gt; is a fairly large routine which demonstrates how you can use a programming pattern called 'a state machine' to process data on-the-fly as it is received from a network connection.&lt;br /&gt;&lt;br /&gt;To demonstrate how to use the &lt;span style="font-style:italic;"&gt;GetURL()&lt;/span&gt; function, I've also added a useful sample script. The script will search your active InDesign document for any page items that have a URL as their script label (entered via &lt;span style="font-style:italic;"&gt;Window - Automation - Script Label&lt;/span&gt;). It will then fetch the data 'behind' the URL and place that data into the page item.&lt;br /&gt;&lt;br /&gt;Install the script &lt;span style="font-style:italic;"&gt;GetURLs.jsx&lt;/span&gt; in the InDesign scripts folder (the easiest is to bring up the scripts palette from InDesign: select &lt;span style="font-style:italic;"&gt;Window - Automation - Scripts&lt;/span&gt;, and then right-click the &lt;span style="font-style:italic;"&gt;User&lt;/span&gt; folder).&lt;br /&gt;&lt;br /&gt;Select &lt;span style="font-style:italic;"&gt;Reveal in Finder&lt;/span&gt; or &lt;span style="font-style:italic;"&gt;Reveal in Explorer&lt;/span&gt;. Then copy the script &lt;span style="font-weight:bold;"&gt;into&lt;/span&gt; the &lt;span style="font-style:italic;"&gt;Scripts Panel&lt;/span&gt; folder you should now see appear.&lt;br /&gt;&lt;br /&gt;Switch back to InDesign, and open up the sample document &lt;span style="font-style:italic;"&gt;GetURLSample.indd&lt;/span&gt;. Run the script &lt;span style="font-style:italic;"&gt;GetURLs.jsx&lt;/span&gt; from the palette by double-clicking it on the palette. The empty frames should fill up with images or text (at least, if you are connected to the Internet).&lt;br /&gt;&lt;br /&gt;So, how does it all work?&lt;br /&gt;&lt;br /&gt;At the heart of it all is the standard ExtendScript object called &lt;span style="font-style:italic;"&gt;Socket&lt;/span&gt;. More info about the &lt;span style="font-style:italic;"&gt;Socket&lt;/span&gt; can be found in the JavaScript Tools Guide for CS3:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.adobe.com/devnet/bridge/pdfs/javascript_tools_guide_cs3.pdf"&gt;http://www.adobe.com/devnet/bridge/pdfs/javascript_tools_guide_cs3.pdf&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The socket object gives us the ability to perform low-level network communications - we can set up TCP/IP connections with other computers on the network.&lt;br /&gt;&lt;br /&gt;The problem is that the Socket object has no higher-level functionality - it has no support for any protocols, like HTTP for example.&lt;br /&gt;&lt;br /&gt;To fix that, you could try and use the protocol support that is available via Bridge with the &lt;span style="font-style:italic;"&gt;HttpConnection&lt;/span&gt; object. You could also forcibly give InDesign access to the &lt;span style="font-style:italic;"&gt;webaccesslib&lt;/span&gt; that is used by Bridge, through some 'fiddling around'.&lt;br /&gt;&lt;br /&gt;However, personally I am not too keen on either of these approaches - they're either a bit too big or too brittle to my liking; I wanted to have an 'InDesign all by itself' solution.&lt;br /&gt;&lt;br /&gt;The alternative approach I used was to provide HTTP support in pure ExtendScript to InDesign.&lt;br /&gt;&lt;br /&gt;Now, before diving into this: be warned, this is NOT a fully fledged, fully compliant HTTP client. I've only implemented a subset of the protocol, just enough to let me do what I needed to do.&lt;br /&gt;&lt;br /&gt;For example, the code only supports UTF-8 text encoding. If your target web server does not offer that you'll have to add some additional code to the scripts to cope with that. Also, I've only implemented HTTP 'GET' requests, not 'POST'. Adding that functionality would be fairly easy to do - it's left as an exercise.&lt;br /&gt;&lt;br /&gt;So, the &lt;span style="font-style:italic;"&gt;Socket&lt;/span&gt; object allows us to send out requests and receive replies via TCP/IP.&lt;br /&gt;&lt;br /&gt;The HTTP protocol is quite extensive, but the basis of it is simple - it is mainly a plain text-based, ping-pong protocol. You send out a request, and you get a reply.&lt;br /&gt;&lt;br /&gt;The (incoming) reply is composed of three parts: a start (or status) line, zero or more header lines, and then an optional body (which can be binary data or text).&lt;br /&gt;&lt;br /&gt;The (outgoing) request is similarly composed of a request line, and zero or more header lines, and an optional body (for POST requests, which I am not implementing here).&lt;br /&gt;&lt;br /&gt;Immediately after the start line, you get zero or more header lines.&lt;br /&gt;&lt;br /&gt;Header lines are themselves separated from the following body of the request or reply by an empty line - so a request or reply always has the same 'rhythm' to it: start line, header lines, empty line, body.&lt;br /&gt;&lt;br /&gt;The &lt;span style="font-style:italic;"&gt;GetURL()&lt;/span&gt; script code in the &lt;span style="font-style:italic;"&gt;GetURLs.jsx&lt;/span&gt; implements this in a rudimentary fashion: the request is a simple multi-line text string, which is fired off to the web server via a Socket object.&lt;br /&gt;&lt;br /&gt;Then the bulk of the code is for interpreting the reply from the web server - there are three levels of decoding that need to happen.&lt;br /&gt;&lt;br /&gt;First of all, we need to decode the reply itself - separate the start/status line from the headers and from the body.&lt;br /&gt;&lt;br /&gt;The headers also will contain some important information: the length of the body that will follow. So we need to interpret that header line in order to know exactly how many bytes to read from the socket.&lt;br /&gt;&lt;br /&gt;At a lower level, we need to 'chop' the reply up into individual lines until we reach the body - the status line and the individual lines are separated by CRLF character pairs (CR = ASCII character 13, LF = ASCII character 10).&lt;br /&gt;&lt;br /&gt;And finally, at the lowest level, while reading a text-based body, we need to interpret UTF-8 code and convert the UTF-8 codes into plain Unicode. This means that we need to read through codes that are 1, 2, 3 or 4 bytes long, and each of them encodes a single Unicode character.&lt;br /&gt;&lt;br /&gt;In the &lt;span style="font-style:italic;"&gt;GetURL()&lt;/span&gt; routine, these three levels of encoding are decoded concurrently, through three nested 'state machines'. Using state machines makes the code fairly fast - much faster than could ever be achieved through string matching.&lt;br /&gt;&lt;br /&gt;I won't go into the intricate details of how &lt;span style="font-style:italic;"&gt;GetURL()&lt;/span&gt; works - the script is fairly well documented and you should be able to figure out how it works by careful reading and stepping through it with the ExtendScript debugger.&lt;br /&gt;&lt;br /&gt;Instead, I want to explain a little bit more about state machines - they are a very powerful technique for fast pattern matching and parsing, and once you 'get' them, they are easy to use. They are used in mechanisms like GREP, in compilers and interpreters, in all kinds of text parsers,...&lt;br /&gt;&lt;br /&gt;All too often I see code that uses straight string functions to achieve some matching goals.&lt;br /&gt;&lt;br /&gt;A simple example: you get some data thrown at you which has line endings that might be either CR (ASCII 13), LF (ASCII 10) or one of each (CRLF).&lt;br /&gt;&lt;br /&gt;Many people will handle that by reading in all the data into a buffer, then do some pattern search-and-replace. For example,&lt;br /&gt;&lt;br /&gt;  first replace all CRLF with CR&lt;br /&gt;  then replace all LF with CR&lt;br /&gt;&lt;br /&gt;After that, the line ending has become a CR throughout the text.&lt;br /&gt;&lt;br /&gt;This approach is not necessarily the best. Especially if you receive the data character by character, you could do the clean-up on-the-fly, as you receive the data. No need to buffer or no global search-and-replaces - so it might greatly reduce the amount of memory you need and also run a lot faster to boot.&lt;br /&gt;&lt;br /&gt;With a state machine, you would go about it as follows. First of all, you create a variable (say, &lt;span style="font-style:italic;"&gt;myState&lt;/span&gt;), and you create some symbolic numerical constants (for example, &lt;span style="font-style:italic;"&gt;kNormalState&lt;/span&gt; could be a symbolic name for 0, and &lt;span style="font-style:italic;"&gt;kSeenCR&lt;/span&gt; could be a symbolic name for 1).&lt;br /&gt;&lt;br /&gt;For more complex state machines there might be hundreds, even thousands of different states - but in this case, two states will do.&lt;br /&gt;&lt;br /&gt;All we'll now do is play with a simple integer variable, and we'll keep track of where we're at by manipulating the state. The idea is that we don't assemble strings or 'memorize' any other input data - we encode the relevant info about 'what has been' into the state variable.&lt;br /&gt;&lt;br /&gt;Data flows through our state machine - we read input data, and immediately get rid of the data - we write or store or process it - and we keep as little data as possible inside our state machine logic.&lt;br /&gt;&lt;br /&gt;So, our little state machine is happily reading and writing character after character.&lt;br /&gt;&lt;br /&gt;After each character we read and process we also check whether it was a CR (ASCII 13) or not, and we change our state to either &lt;span style="font-style:italic;"&gt;kNormalState&lt;/span&gt; or &lt;span style="font-style:italic;"&gt;kSeenCR&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Now, suppose we now read a line feed character (ASCII 10). Before doing anything with a new character, the state machine will always check its current state first.&lt;br /&gt;&lt;br /&gt;If the state is &lt;span style="font-style:italic;"&gt;kSeenCR&lt;/span&gt; we know that this is a line feed after a preceding CR, so we simply &lt;span style="font-weight:bold;"&gt;don't&lt;/span&gt; write the LF out.&lt;br /&gt;&lt;br /&gt;If we read a LF and the state is &lt;span style="font-style:italic;"&gt;kNormalState&lt;/span&gt;, we know that this is a 'stand alone' LF without preceding CR - so we output a CR character to replace it instead.&lt;br /&gt;&lt;br /&gt;The state machine is just simple enough to express in words:&lt;br /&gt;&lt;br /&gt;Initialize myState to kNormalState &lt;br /&gt;read character (loop until end of file)&lt;br /&gt;&lt;br /&gt;  if character is LF then &lt;br /&gt;    if myState is NOT kSeenCR then &lt;br /&gt;      output CR &lt;br /&gt;    end if&lt;br /&gt;  else &lt;br /&gt;    output character &lt;br /&gt;  end if&lt;br /&gt;&lt;br /&gt;  if character is CR then &lt;br /&gt;    myState becomes kSeenCR &lt;br /&gt;  else &lt;br /&gt;    myState becomes kNormalState &lt;br /&gt;  end if&lt;br /&gt;&lt;br /&gt;end loop&lt;br /&gt;&lt;br /&gt;This might seem overkill, but the advantages of state machines become apparent when you try more complex things - for example, interpreting a quote JavaScript string. That string might contain escape-sequences (backslash, followed by a letter, or 1-3 octal digits). Properly interpreting such an 'escaped' string is hard work without a state machine. With a state machine it's a breeze, with hardly any overhead.&lt;br /&gt;&lt;br /&gt;So, that was a quick introduction to state machines - I hope it was enough to pique your interest, and entice you to do a bit of research; once you've added them to your arsenal of techniques, you'll find that some difficult tasks have become a lot easier.&lt;br /&gt;&lt;br /&gt;You can download the sample files from the following URL (which is mentioned in the podcast transcript):&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.rorohiko.com/podcast/geturl.zip"&gt;http://www.rorohiko.com/podcast/geturl.zip&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1401434775260820755-7418105582007685987?l=rorohiko.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=4NEgfBby"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=378LqJrL"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=42" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=CQXsL5g3"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=UY1wsi6y"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?i=UY1wsi6y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=cR5fEUTe"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=pQ6fgxC3"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?i=pQ6fgxC3" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=YYTxu7Ar"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?i=YYTxu7Ar" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=5UdJj8Pu"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=134" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rorohiko/~4/LudYNykZzxQ" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2008-07-12T00:37:13.521-07:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><media:content url="http://feedproxy.google.com/~r/Rorohiko/~5/tZzlv5A6kp4/geturl.zip" fileSize="624876" type="application/zip" /><itunes:explicit>no</itunes:explicit><itunes:subtitle>Sample files for this podcast can be downloaded from: http://www.rorohiko.com/podcast/geturl.zip This podcast will explain how you can query web services from within InDesign CS3 ExtendScript. No need for plug-ins, external libraries - just Adobe InDesign</itunes:subtitle><itunes:author>Kris Coppieters</itunes:author><itunes:summary>Sample files for this podcast can be downloaded from: http://www.rorohiko.com/podcast/geturl.zip This podcast will explain how you can query web services from within InDesign CS3 ExtendScript. No need for plug-ins, external libraries - just Adobe InDesign ExtendScript, pure and simple. I'll also present some useful routines I wrote, called GetURL() and ParseURL(). GetURL() is a fairly large routine which demonstrates how you can use a programming pattern called 'a state machine' to process data on-the-fly as it is received from a network connection. To demonstrate how to use the GetURL() function, I've also added a useful sample script. The script will search your active InDesign document for any page items that have a URL as their script label (entered via Window - Automation - Script Label). It will then fetch the data 'behind' the URL and place that data into the page item. Install the script GetURLs.jsx in the InDesign scripts folder (the easiest is to bring up the scripts palette from InDesign: select Window - Automation - Scripts, and then right-click the User folder). Select Reveal in Finder or Reveal in Explorer. Then copy the script into the Scripts Panel folder you should now see appear. Switch back to InDesign, and open up the sample document GetURLSample.indd. Run the script GetURLs.jsx from the palette by double-clicking it on the palette. The empty frames should fill up with images or text (at least, if you are connected to the Internet). So, how does it all work? At the heart of it all is the standard ExtendScript object called Socket. More info about the Socket can be found in the JavaScript Tools Guide for CS3: http://www.adobe.com/devnet/bridge/pdfs/javascript_tools_guide_cs3.pdf The socket object gives us the ability to perform low-level network communications - we can set up TCP/IP connections with other computers on the network. The problem is that the Socket object has no higher-level functionality - it has no support for any protocols, like HTTP for example. To fix that, you could try and use the protocol support that is available via Bridge with the HttpConnection object. You could also forcibly give InDesign access to the webaccesslib that is used by Bridge, through some 'fiddling around'. However, personally I am not too keen on either of these approaches - they're either a bit too big or too brittle to my liking; I wanted to have an 'InDesign all by itself' solution. The alternative approach I used was to provide HTTP support in pure ExtendScript to InDesign. Now, before diving into this: be warned, this is NOT a fully fledged, fully compliant HTTP client. I've only implemented a subset of the protocol, just enough to let me do what I needed to do. For example, the code only supports UTF-8 text encoding. If your target web server does not offer that you'll have to add some additional code to the scripts to cope with that. Also, I've only implemented HTTP 'GET' requests, not 'POST'. Adding that functionality would be fairly easy to do - it's left as an exercise. So, the Socket object allows us to send out requests and receive replies via TCP/IP. The HTTP protocol is quite extensive, but the basis of it is simple - it is mainly a plain text-based, ping-pong protocol. You send out a request, and you get a reply. The (incoming) reply is composed of three parts: a start (or status) line, zero or more header lines, and then an optional body (which can be binary data or text). The (outgoing) request is similarly composed of a request line, and zero or more header lines, and an optional body (for POST requests, which I am not implementing here). Immediately after the start line, you get zero or more header lines. Header lines are themselves separated from the following body of the request or reply by an empty line - so a request or reply always has the same 'rhythm' to it: start line, header lines, empty line, body. The GetURL() script code in the GetURLs.jsx implements this in a rudimentary fashion: the req</itunes:summary><itunes:keywords>printing,prepress,automation,InDesign,Adobe,CS,CS2,CS3,Rorohiko,plug,in,plugin,software,consultancy,design,desktop,publishing,PDF,Acrobat,XPress,QuarkXPress,XTension</itunes:keywords><feedburner:origLink>http://rorohiko.blogspot.com/2008/07/lightning-brain-podcast-click-here-to.html</feedburner:origLink><enclosure url="http://feedproxy.google.com/~r/Rorohiko/~5/tZzlv5A6kp4/geturl.zip" length="624876" type="application/zip" /><feedburner:origEnclosureLink>http://www.rorohiko.com/podcast/geturl.zip</feedburner:origEnclosureLink></item><item><title>Lightning Brain Podcast: Click here to listen to "How To Get Paid For Writing ExtendScripts For Adobe® InDesign®"</title><link>http://feedproxy.google.com/~r/Rorohiko/~3/CasDfTq8NiM/lightning-brain-podcast-click-here-to.html</link><author>kris@rorohiko.com (Kris Coppieters)</author><pubDate>Sun, 30 Mar 2008 22:03:22 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-1401434775260820755.post-2456688913950986757</guid><description>&lt;p&gt;In this podcast, I'll be highlighting a single feature of Rorohiko's &lt;em&gt;Active Page Items&lt;/em&gt; family of tools that can help you get paid for ExtendScripts you write for Adobe InDesign CS, CS2 or CS3.&lt;/p&gt;      &lt;p&gt;To demonstrate how easy it is, I've first created an ExtendScript called &lt;em&gt;FlontFipper&lt;/em&gt;. The script itself, and its name, are a bit tongue-in-cheek, but actually might be useful, who knows?&lt;/p&gt;      &lt;p&gt;What the script does is look at the currently active document and determine which two fonts are used most often in the document. It then swaps these fonts.&lt;/p&gt;      &lt;p&gt;For example, if your document is quite simple, and has headlines in Helvetica and body text in Times Roman, this script would make the headlines Times Roman, and the body text would become Helvetica.&lt;/p&gt;      &lt;p&gt;To use the script, the end-user would install the script into the appropriate folder for InDesign scripts. Then he would open a document, and double-click the script name in the InDesign Scripts panel.&lt;/p&gt;      &lt;p&gt;Now assume I would like to sell this script to InDesign users.&lt;/p&gt;      &lt;p&gt;First of all, I need to download a copy of the &lt;a href="http://www.rorohiko.com/frame-pages/r-activepageitemdeveloper.html"&gt;&lt;em&gt;APIDToolkit&lt;/em&gt; (&lt;em&gt;Active Page Items Developer Toolkit&lt;/em&gt;)&lt;/a&gt;. A functional, time-limited demo version of &lt;em&gt;&lt;a href="http://www.rorohiko.com/frame-pages/r-activepageitemdeveloper.html"&gt;APIDToolkit&lt;/a&gt; &lt;/em&gt;is available from the Rorohiko web site.&lt;/p&gt;      &lt;p&gt;This toolkit contains lots of stuff, but the single item I am interested in for this podcast is called the &lt;em&gt;InDesignScriptCompiler&lt;/em&gt;. Mac and PC versions are provided in the downloadable archive file.&lt;/p&gt;      &lt;p&gt;Second, my potential customer needs to install a special runtime plug-in (the &lt;a href="http://www.rorohiko.com/frame-pages/r-activepageitemdeveloper.html"&gt;&lt;em&gt;APIDKernel&lt;/em&gt;&lt;/a&gt;) which will enforce the demo- and licensing restrictions I want to impose on the use of my FlontFipper script.&lt;/p&gt;      &lt;p&gt;To protect my &lt;em&gt;FlontFipper.jsx&lt;/em&gt; script, I simply drag/drop it onto the &lt;em&gt;InDesignScriptCompiler&lt;/em&gt; icon, and fill in some parameters - mainly to tell &lt;em&gt;APID&lt;/em&gt; what the limitations are for the demo mode and via which URL a license can be purchased from me.&lt;/p&gt;      &lt;p&gt;The result is an encrypted and protected version of my script - &lt;em&gt;FlontFipper.compiled.js&lt;/em&gt; - which I can then send to my prospective customer, the end user.&lt;/p&gt;      &lt;p&gt;My end user then installs &lt;em&gt;FlontFipper.compiled.js&lt;/em&gt; just like any normal script, and uses it just like he would use the non-encrypted original. Note that this is also supported on InDesign CS and CS2.&lt;/p&gt;      &lt;p&gt;The main difference with an uncompiled script is that each time InDesign is restarted, the first time &lt;em&gt;FlontFipper&lt;/em&gt; is used, a 'beg' dialog will appear, which will inform the end-user of the time-limited nature of the &lt;em&gt;FlontFipper&lt;/em&gt; demo. There are also two buttons on the dialog: &lt;em&gt;Get License...&lt;/em&gt; and &lt;em&gt;Import License File...&lt;/em&gt;.&lt;/p&gt;      &lt;p&gt;If the end-user clicks &lt;em&gt;Get License...&lt;/em&gt; his system's web browser will be directed to display the embedded URL, and it will pass through all the data I would need to create a personalized license file for my end-user.&lt;/p&gt;      &lt;p&gt;I then proceed through some monetary transaction to receive the payment from the end-user.&lt;/p&gt;      &lt;p&gt;How this transaction is conducted is up to the script developer - for example, I could set up a fully automatic web-based pay-and-license system, or I could simply use a manual system based on e-mail.&lt;/p&gt;      &lt;p&gt;&lt;em&gt;APID&lt;/em&gt; does not dictate how this transaction should be implemented - this part of the system is left open, and for the script developer to fill in.&lt;/p&gt;      &lt;p&gt;Once I receive payment from the end-user I will then use the data I received via the URL to generate a license file, which I then e-mail to the end-user.&lt;/p&gt;      &lt;p&gt;The end-user uses the license file to convert the time-limited demo of my script into a fully functional version.&lt;/p&gt;      &lt;p&gt;The next time the beg dialog appears, he clicks &lt;em&gt;Import License File...&lt;/em&gt; and imports the license file I sent. From then on &lt;em&gt;FlontFipper.compiled.js&lt;/em&gt; will not show any more beg dialogs, and also will not lapse.&lt;/p&gt;      &lt;p&gt;If you want to try these things out: go to&lt;br /&gt;      &lt;br /&gt;      www.rorohiko.com/flontfipper.html&lt;br /&gt;      &lt;br /&gt;(all lowercase): you can see the transcript of this podcast with additional screenshots, and you can download the source code, the compiled script, and a license file to test things out.&lt;/p&gt;      &lt;p&gt;I'll now dive a bit more into the details of the compilation. After I drag-drop my script onto the script compiler, I get to see a main dialog named &lt;em&gt;APID Standalone Script Compiler&lt;/em&gt;.&lt;/p&gt;      &lt;p&gt;&lt;img src="http://www.rorohiko.com/podcast/flontfipper1.png" alt="" border="0" width="80%" /&gt;&lt;/p&gt;      &lt;p&gt;Here I must define how the compiled script will behave. The most important field is a 'Component ID' string. It has quite a few subfields separated by semicolons and commas and is most easily edited by clicking the 'Edit...' button next to it.&lt;/p&gt;      &lt;p&gt;Clicking the Edit... button shows the 'Component ID' dialog. In the 'Component ID' Dialog, I need to define a number of parameters&lt;/p&gt;      &lt;p&gt;&lt;img src="http://www.rorohiko.com/podcast/flontfipper2.png" alt="" border="0" width="80%" /&gt;&lt;/p&gt;      &lt;p&gt;- a 'component name' which I set to be &lt;em&gt;FlontFipper&lt;/em&gt; - this is the name that will appear in various dialogs&lt;br /&gt;      - a 'compilation password' which will be used in the encryption of the script - in this sample, I made te password &lt;em&gt;guessWhat&lt;/em&gt;&lt;br /&gt;      - a copyright string&lt;/p&gt;      &lt;p&gt;These first three strings are mainly about identifying your compiled script.&lt;/p&gt;      &lt;p&gt;In this same dialog there are also a number of fields to restrict the use of your compiled script - there is a minimum APID version (which I set to 1.0.44 or 1.044 - the current version at the time of this podcast - the &lt;em&gt;InDesignScriptCompiler&lt;/em&gt; will drop the leading zeroes automatically and display 1.44).&lt;/p&gt;      &lt;p&gt;There is also a hard cut-off date for demo versions. Because I don't want to use such a date in this demo, I've set the three date-subfields (year, month, day) to zero.&lt;/p&gt;      &lt;p&gt;The most interesting fields for me are the number of 'actual use' days and number of demo days.&lt;/p&gt;      &lt;p&gt;&lt;em&gt;#Demo days&lt;/em&gt; represents a number of calendar days since the first use of your script by the end user; 30 days here would mean 'about a month'.&lt;/p&gt;      &lt;p&gt;&lt;em&gt;#Actual Use Days&lt;/em&gt; represent days of actual use; these days are not necessarily consecutive. This is provided to cater for situations with 'infrequent use' - people that only test the script every so often, and might leave long gaps between uses; you could leave &lt;em&gt;#Demo days&lt;/em&gt; set to -1, and &lt;em&gt;#Actual Use Days&lt;/em&gt; for example set to 5 and the user would be able to try things out for 5 non-consecutive days.&lt;/p&gt;      &lt;p&gt;You can use either, or both fields to limit how long a demo version of your script should be usable.&lt;/p&gt;      &lt;p&gt;In this sample, I've set the actual use days to 20, and the calendar days to 30 - the demo will time out after 20 days of actual use, or 30 calendar days, whichever comes first.&lt;/p&gt;      &lt;p&gt;There is also a checkbox &lt;em&gt;Free&lt;/em&gt; which I'd only use if I don't want to sell my script - for example if I just want to give encrypted versions away without divulging my source code. This checkbox is deselected in my example - I want to sell my script.&lt;/p&gt;      &lt;p&gt;On the main screen, I must also enter some messages and a &lt;em&gt;License URL&lt;/em&gt;.&lt;/p&gt;      &lt;p&gt;The URL is set to link to a web page on my web server, and it passes 4 parameters as part of the URL: the serial number of InDesign, the name of the script (as defined in the Component ID dialog), the system identifier (a unique identifier for the computer requesting a license), and a license level (which will be a letter 'D' or 'R' depending on whether the end-user already has purchased a proper license for &lt;em&gt;APIDKernel&lt;/em&gt; or not) - the strings ^1, ^2, ^3, and ^4 are placeholders that are replaced by real data when the URL is needed.&lt;/p&gt;      &lt;p&gt;There are also two messages that can appear in the beg dialog. In these messages, ^1 is a placeholder for the compiled script name (as defined in the component ID earlier on), and ^2 is a placeholder for the remaining number of demo days.&lt;/p&gt;      &lt;p&gt;Once I click &lt;em&gt;Compile for APIDKernel&lt;/em&gt; two things will happen: a compiled version of my script will be created (&lt;em&gt;FlontFipper.compiled.js&lt;/em&gt;), and my original source code will also be prefixed with a few comment lines that store my compilation parameters - this to avoid having to re-enter the same stuff next time around.&lt;/p&gt;      &lt;p&gt;When a user installs &lt;em&gt;FlontFipper.compiled.js&lt;/em&gt; in one of the proper script locations for Adobe InDesign, the script will behave mostly like any other script, except for the beg dialog. Clicking &lt;em&gt;Get License...&lt;/em&gt; on the beg dialog makes the end-users' system browser connect to the URL embedded into the compiled script.&lt;/p&gt;      &lt;p&gt;&lt;img src="http://www.rorohiko.com/podcast/flontfipper3.png" alt="" border="0" width="90%" /&gt;&lt;/p&gt;      &lt;p&gt;Once I receive payment from the end-user, I use a command-line tool that is part of the &lt;em&gt;APIDToolkit&lt;/em&gt; to generate a license file for him. Mac and Windows versions of this tool are provided. If so desired, this command-line tool can be embedded into a web server setup - this is how Rorohiko does automated software sales, for example of our Sudoku Generator.&lt;/p&gt;      &lt;p&gt;&lt;img src="http://www.rorohiko.com/podcast/flontfipper4.png" alt="" border="0" width="90%" /&gt;&lt;/p&gt;      &lt;p&gt;Note that the command line tool is not provided with the demo version of &lt;em&gt;APIDToolkit&lt;/em&gt; - you need to purchase the &lt;em&gt;APIDToolkit&lt;/em&gt; to get access to this generator - a license for the &lt;em&gt;APIDToolkit&lt;/em&gt; costs US$149.00.&lt;/p&gt;      &lt;p&gt;For simple set-ups you can also create 'generic' license files which are not linked to any particular system ID or InDesign serial number. The demo license file for this podcast is such a generic license file. It will enable &lt;em&gt;FlontFipper.compiled.js&lt;/em&gt; on any copy of InDesign.&lt;/p&gt;      &lt;p&gt;Costwise, the &lt;em&gt;APIDKernel&lt;/em&gt; runtime for your end-user is not free - there is a one-time cost of US$25 or less per seat.&lt;/p&gt;      &lt;p&gt;Note: there are multi-seat &lt;em&gt;APIDKernel&lt;/em&gt; bundles available. These should only be used for a single end-user company. For example, you're not meant to purchase a 100-seat &lt;em&gt;APIDKernel&lt;/em&gt; and then break these up and sell individual seats to different end-user companies.&lt;/p&gt;      &lt;p&gt;Another point worth noting is that &lt;em&gt;APIDKernel&lt;/em&gt; licenses are linked to a particular serial number of InDesign, as well as to a unique system identifier. That means that if your customer is using both InDesign CS2 and CS3 on the same computer, he'll need to purchase two licenses for &lt;em&gt;APIDKernel&lt;/em&gt;.&lt;/p&gt;      &lt;p&gt;Depending on how you set things up, there can be two payments to be made by a first-time end-user. First of all, the end-user needs a license for the &lt;em&gt;APIDKernel&lt;/em&gt;, and second, he needs a license for your script.&lt;/p&gt;      &lt;p&gt;It is up to you, as a script developer, to decide how to handle the cost for &lt;em&gt;APIDKernel&lt;/em&gt;.&lt;/p&gt;      &lt;p&gt;You can bundle a pre-purchased coupon code for a license for the kernel when you sell your script, or you can ask your customer to license the kernel directly from Rorohiko. That means you can choose to either have a single monetary transaction between the end-user and you, or there can be two separate transactions&lt;br /&gt;      - between the end-user and you for your script&lt;br /&gt;      - between the end-user and Rorohiko for &lt;em&gt;APIDKernel&lt;/em&gt;&lt;/p&gt;      &lt;p&gt;Since version 1.0.44, there is also an option to provide your end-user with a single, combined license file which contains both a license for &lt;em&gt;APIDKernel&lt;/em&gt; and a license for your script - contact &lt;a href="mailto:APIDlicenses@rorohiko.com"&gt;APIDlicenses@rorohiko.com&lt;/a&gt; for more info; for this system to be available to you, you need to register with Rorohiko as an APID developer.&lt;/p&gt;      &lt;p&gt;Lastly, if you expect to sell more than a few thousand copies of your script, you should probably consider our &lt;em&gt;APIE/APIR&lt;/em&gt; combo - these are two other family members of the &lt;em&gt;Active Page Items&lt;/em&gt; family. &lt;em&gt;APIR&lt;/em&gt; is a runtime which is very similar to &lt;em&gt;APIDKernel&lt;/em&gt;, except that it is free for end-users - there is no cost to the end-user for the &lt;em&gt;APIR&lt;/em&gt; runtime.&lt;/p&gt;      &lt;p&gt;To generate solutions that can use the free &lt;em&gt;APIR&lt;/em&gt; instead of &lt;em&gt;APIDKernel&lt;/em&gt;, you'd need to license &lt;em&gt;APIE&lt;/em&gt; - which is a more expensive version of &lt;em&gt;APIDToolkit&lt;/em&gt;, and can create solutions that work with the free &lt;em&gt;APIR&lt;/em&gt; instead of the non-free &lt;em&gt;APIDKernel&lt;/em&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1401434775260820755-2456688913950986757?l=rorohiko.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=Sc05zkpS"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=1BRyHEWo"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=42" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=TAHNb9iC"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=UxAaGgc4"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?i=UxAaGgc4" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=B8klfaSj"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=hVTjTxEn"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?i=hVTjTxEn" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=DBP7DwZ9"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?i=DBP7DwZ9" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=KZxhnHjP"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=134" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rorohiko/~4/CasDfTq8NiM" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2008-03-30T22:03:22.012-07:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><media:content url="http://feedproxy.google.com/~r/Rorohiko/~5/zTd4WzP_hDA/APID.mp3" fileSize="5472232" type="audio/mpeg" /><itunes:explicit>no</itunes:explicit><itunes:subtitle> In this podcast, I'll be highlighting a single feature of Rorohiko's Active Page Items family of tools that can help you get paid for ExtendScripts you write for Adobe InDesign CS, CS2 or CS3. To demonstrate how easy it is, I've first created an ExtendSc</itunes:subtitle><itunes:author>Kris Coppieters</itunes:author><itunes:summary> In this podcast, I'll be highlighting a single feature of Rorohiko's Active Page Items family of tools that can help you get paid for ExtendScripts you write for Adobe InDesign CS, CS2 or CS3. To demonstrate how easy it is, I've first created an ExtendScript called FlontFipper. The script itself, and its name, are a bit tongue-in-cheek, but actually might be useful, who knows? What the script does is look at the currently active document and determine which two fonts are used most often in the document. It then swaps these fonts. For example, if your document is quite simple, and has headlines in Helvetica and body text in Times Roman, this script would make the headlines Times Roman, and the body text would become Helvetica. To use the script, the end-user would install the script into the appropriate folder for InDesign scripts. Then he would open a document, and double-click the script name in the InDesign Scripts panel. Now assume I would like to sell this script to InDesign users. First of all, I need to download a copy of the APIDToolkit (Active Page Items Developer Toolkit). A functional, time-limited demo version of APIDToolkit is available from the Rorohiko web site. This toolkit contains lots of stuff, but the single item I am interested in for this podcast is called the InDesignScriptCompiler. Mac and PC versions are provided in the downloadable archive file. Second, my potential customer needs to install a special runtime plug-in (the APIDKernel) which will enforce the demo- and licensing restrictions I want to impose on the use of my FlontFipper script. To protect my FlontFipper.jsx script, I simply drag/drop it onto the InDesignScriptCompiler icon, and fill in some parameters - mainly to tell APID what the limitations are for the demo mode and via which URL a license can be purchased from me. The result is an encrypted and protected version of my script - FlontFipper.compiled.js - which I can then send to my prospective customer, the end user. My end user then installs FlontFipper.compiled.js just like any normal script, and uses it just like he would use the non-encrypted original. Note that this is also supported on InDesign CS and CS2. The main difference with an uncompiled script is that each time InDesign is restarted, the first time FlontFipper is used, a 'beg' dialog will appear, which will inform the end-user of the time-limited nature of the FlontFipper demo. There are also two buttons on the dialog: Get License... and Import License File.... If the end-user clicks Get License... his system's web browser will be directed to display the embedded URL, and it will pass through all the data I would need to create a personalized license file for my end-user. I then proceed through some monetary transaction to receive the payment from the end-user. How this transaction is conducted is up to the script developer - for example, I could set up a fully automatic web-based pay-and-license system, or I could simply use a manual system based on e-mail. APID does not dictate how this transaction should be implemented - this part of the system is left open, and for the script developer to fill in. Once I receive payment from the end-user I will then use the data I received via the URL to generate a license file, which I then e-mail to the end-user. The end-user uses the license file to convert the time-limited demo of my script into a fully functional version. The next time the beg dialog appears, he clicks Import License File... and imports the license file I sent. From then on FlontFipper.compiled.js will not show any more beg dialogs, and also will not lapse. If you want to try these things out: go to www.rorohiko.com/flontfipper.html (all lowercase): you can see the transcript of this podcast with additional screenshots, and you can download the source code, the compiled script, and a license file to test things out. I'll now dive a bit more into the details of the compilation. After I drag-drop my script onto the</itunes:summary><itunes:keywords>printing,prepress,automation,InDesign,Adobe,CS,CS2,CS3,Rorohiko,plug,in,plugin,software,consultancy,design,desktop,publishing,PDF,Acrobat,XPress,QuarkXPress,XTension</itunes:keywords><feedburner:origLink>http://rorohiko.blogspot.com/2008/03/lightning-brain-podcast-click-here-to.html</feedburner:origLink><enclosure url="http://feedproxy.google.com/~r/Rorohiko/~5/zTd4WzP_hDA/APID.mp3" length="5472232" type="audio/mpeg" /><feedburner:origEnclosureLink>http://www.rorohiko.com/mp3/APID.mp3</feedburner:origEnclosureLink></item><item><title>Lightning Brain Podcast: Click here to listen to "Refactoring ExtendScripts"</title><link>http://feedproxy.google.com/~r/Rorohiko/~3/8YFEPp-n6vM/lightning-brain-podcast-click-here-to.html</link><author>kris@rorohiko.com (Kris Coppieters)</author><pubDate>Fri, 07 Dec 2007 17:09:39 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-1401434775260820755.post-7920773274453138684</guid><description>Today we'll talk about cleaning up scripts, and as a bonus, we'll work on a script that adds a 'hand-written' quality to text: changing something like this:&lt;br /&gt;&lt;br /&gt;&lt;img alt='Before Jitter' src='http://www.rorohiko.com/podcast/jitterbefore.png' width="90%"/&gt;&lt;br /&gt;&lt;br /&gt;into&lt;br /&gt;&lt;br /&gt;&lt;img alt='Before Jitter' src='http://www.rorohiko.com/podcast/jitterafter.png' width="90%"/&gt;&lt;br /&gt;&lt;br /&gt;By clicking the link provided in this sentence, you can download this real-life example of a small script being refactored, from experimental form to a cleaner form - click &lt;a href="http://www.rorohiko.com/podcast/JitterScripts.zip"&gt;here&lt;/a&gt; to download &lt;a href="http://www.rorohiko.com/podcast/JitterScripts.zip"&gt;JitterScripts.zip&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Listen to or read the podcast transcript for more info...&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;On to the podcast - click &lt;a href="http://www.rorohiko.com/mp3/JitterScripts.mp3"&gt;here&lt;/a&gt; to listen to it!&lt;/h3&gt;&lt;br /&gt;So, the script works, everyone is happy - but maybe you are not done yet...&lt;br /&gt;&lt;br /&gt;Imagine that you will have to pick that same script up again twelve months from now. How much time will it take you to 'get back up to speed' and rebuild a mental picture of the script and what it is doing? Probably it will take you many hours of browsing, debugging and fiddling around before you regain enough understanding of the script's inner workings to make a 'safe' change.&lt;br /&gt;&lt;br /&gt;Now, what if the circumstances have changed, and the script needs to be adjusted to cope with a new environment - it might need to be moved from InDesign to InDesign Server, there might be new requirements...&lt;br /&gt;&lt;br /&gt;How about spending some time now - when your head is still filled with knowledge about how it all works - and make sure the script becomes more future-proof. &lt;br /&gt;&lt;br /&gt;In this podcast, I'll list a few of the techniques I personally use to 'future-proof' my scripts. &lt;br /&gt;&lt;br /&gt;Before diving into the techniques, I need to explain how we approach ExtendScript development here at Rorohiko; we've adapted an approach that delivers very good quality at a reasonable price - we're not cheap, but as opposed to many other custom developments, our solutions work and work well.&lt;br /&gt;&lt;br /&gt;When we're developing custom scripts, we use a 'no cure, no pay' approach, for a number of reasons. &lt;br /&gt;&lt;br /&gt;The main reason is, that for this type of development, building a sufficiently accurate quote often costs us more than the development itself. &lt;br /&gt;&lt;br /&gt;For an accurate quote, we would first and foremost need an accurate, extensive project brief.&lt;br /&gt;&lt;br /&gt;But in our business we're often dealing with creative, fairly a-technical people, and we invariably found it very hard, even impossible to zoom in on an accurate enough technical description of the functionality being looked for.&lt;br /&gt;&lt;br /&gt;On top of that, what we're asked to do is often at odds with what is really needed. We're often asked to develop a specific &lt;i&gt;solution&lt;/i&gt;, rather than being asked to solve a &lt;i&gt;problem&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;From experience we've learned that it pays to dig deeper, and try and find out what the underlying problem is - quite often the asked-for 'solution' only cures a symptom, and leaves the underlying problem unfixed.&lt;br /&gt;&lt;br /&gt;The most efficient way we found to get the technical information we need from creative people is to use an iterative approach. Instead nagging people and trying to wring a technical brief out of them, we put the cart before the horse instead, and we create something, anything, as good as we can, based on the still limited understanding we have of the problem at hand.&lt;br /&gt;&lt;br /&gt;We present our customer with the attempted solution, and get their feedback - it is much easier for them to explain what is wrong or what is missing from some tangible, real software, rather than trying to come up with blueprint.&lt;br /&gt;&lt;br /&gt;Based on the feedback, we adjust the solution (or throw it out and start over), and we go through a few iterations, until we have the thing sussed.&lt;br /&gt;&lt;br /&gt;Eventually, we reach a good, smooth solution, and by that time we also know exactly what the cost of that solution is. &lt;br /&gt;&lt;br /&gt;At that point, the 'no cure, no pay' system kicks in: our customer can choose to purchase and continue to use the software, or alternatively, in case our solution were to not live up to its promise, the software is simply destroyed, and there is no cost to the customer.&lt;br /&gt;&lt;br /&gt;This approach works really well, but the successive iterations cause the software to go through a few swings and roundabouts, and along the way, grow a whole collection of warts if we're not careful.&lt;br /&gt;&lt;br /&gt;We'll typically spend some time refactoring the scripts to make sure they're future-proof and self-explanatory - making a small investment of time now in return for a substantial time-saving later.&lt;br /&gt;&lt;br /&gt;Here are some of the things we do:&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;1) Don't rely on app.activeDocument&lt;/h3&gt;&lt;br /&gt;While in the heat of experimentation, iteration and script development, it's easy to assume that the functionality being created will be applied to the current document, and hence to refer to app.activeDocument&lt;br /&gt;&lt;br /&gt;However, there are sizable benefits to removing the reliance on the active document. Our scripts will typically contain a number of functions, and whenever a function uses app.activeDocument, we rework that function to not use 'app.activeDocument', but instead take a 'document' parameter. &lt;br /&gt;&lt;br /&gt;The idea is that you get hold of the document 'under consideration' in one single spot in the script, and that from then on you pass a document parameter to any function that is supposed to work on that document.&lt;br /&gt;&lt;br /&gt;The two biggest advantages are:&lt;br /&gt;&lt;br /&gt;First, your script becomes a lot easier to convert to an InDesign Server environment (where there is no such thing as app.activeDocument), and second, all of your functions have now suddenly become much more re-usable: they can now also be used when the document to be modified is not the active document. &lt;br /&gt;&lt;br /&gt;For example, the document might be a temporary, invisible document you're opening in the background - and by NOT using app.activeDocument, you can pass such a document to your functions as a parameter. &lt;br /&gt;&lt;br /&gt;&lt;h3&gt;2) Test, test, test your preconditions&lt;/h3&gt;&lt;br /&gt;When using a function, it pays to add tests for preconditions - make sure all parameters being passed as what they are supposed to be, and display an error message if they are not. Whenever possible, we leave all this testing code in the script - so if something goes wrong at the customer's end we get good, specific information about where things go off the rails.&lt;br /&gt;&lt;br /&gt;Typically, we'll have a global constant - something like kDebugging - which can be set to true or false to indicate debugging more. &lt;br /&gt;&lt;br /&gt;We'll also add a messaging function similar to alert() which can display a dialog box with a message. The difference with alert() is that the dialog box is conditional on kDebugging being set to true. If kDebugging is set to false, the message is ignored.&lt;br /&gt;&lt;br /&gt;And then we'll test all the function parameters being passed into a function. Is the document non-null? Is it instanceof Document? Is the percentage a number between 0 and 100? If any of these tests fail, a debug message is emitted, and the function 'bails out'.  This guarantees that any unexpected condition can be caught early on.&lt;br /&gt;&lt;br /&gt;This works well by wrapping most of the function body inside a do{}while(false) construct, which mis-uses the do-while loop to build a construct that allows a 'ladder-like' function construction. &lt;br /&gt;&lt;br /&gt;Inside the do{}while(false) there is a whole series of if tests which verify if all is well, and display a debug message followed by a 'break' statement if not. The break causes the function to 'fall off' the ladder for any failing precondition. The debug message being displayed is specific enough to pinpoint the spot where things went wrong - it will include the name of the function where the problem occurs, and a short description of what is wrong.&lt;br /&gt;&lt;br /&gt;This construct is quite similar to using try-catch, but it is 'cheaper' in a number of respects; it causes less overhead than using try-catch, and does not cause the InDesign Debug version to emit assert statements during script execution.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;3) Do not spend time optimizing unless it is really necessary.&lt;/h3&gt;&lt;br /&gt;Now, you'd think that all that debug code from the previous point must cause a lot of overhead.&lt;br /&gt;&lt;br /&gt;Well, turns out that is not true most of the time - a typical script will spend 95% of its time in 5% of the script, and all that debug code has very little impact on the script execution time.&lt;br /&gt;&lt;br /&gt;In practice, we'll leave all our debug code in the script - all we might do is to set kDebugging (or whatever the constant is called) to false - but even that we often don't do: it's better to be informed of unexpected circumstances, than to have a script silently and mysteriously fail.&lt;br /&gt;&lt;br /&gt;Only when there are speed issues might we consider removing some debugging code - but only if we can clearly see that this code is part of the bottleneck. &lt;br /&gt;&lt;br /&gt;The current ExtendScript Toolkit contains a nice profiling tool that allows you to see where a script is spending most of its time. Our recommendation is to not bother with optimizing unless there is a time issue, and when optimizing, use proper profiling to solve the bottleneck - but nothing else. Any debug code that you can leave alone should be left alone; it's part of your safety net.&lt;br /&gt;&lt;br /&gt;It is very common for our scripts to have 50% or more debugging/testing code in them.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;4) Avoid global variables&lt;/h3&gt;&lt;br /&gt;While experimenting, it is very common and easy to introduce some global variables to keep track of things. &lt;br /&gt;&lt;br /&gt;However, global variables can be a recipe for disaster - especially when you need to revisit an older script and make some modifications to it.&lt;br /&gt;&lt;br /&gt;Global variables represent a form of communication between different areas of your script - functions can communicate with one another by stuffing data into global variables, and getting it back out again.&lt;br /&gt;&lt;br /&gt;Problem is: that type of interaction is very easy to get overlooked, and causes all kinds of unexpected side effects - for example, you add an extra call to a particular function somewhere, the function changes a value of some global variable, and then other functions that rely on that same variable go off the rails.&lt;br /&gt;&lt;br /&gt;Because functions don't clearly 'advertise' what global data they consult or modify, it becomes very hard to keep track of interactions. That makes for fun debug sessions, chasing weird bugs after making a 'tiny change' to a year-old script.&lt;br /&gt;&lt;br /&gt;Like everyone else, during the initial phase of a project, we often start out stuffing data into globals - but unless there is good reason to, we'll rework the script and move the global variables into function parameters. If there is a lot of data, we'll introduce one or more data structures which are then passed around as a parameter.&lt;br /&gt;&lt;br /&gt;An example: we might be parsing a text string, and keep track of where we're at in a global variable gTextPos, and store the string in a global gParseText. &lt;br /&gt;&lt;br /&gt;During cleanup, that will be reworked (or 'refactored' as it is often called) - we'll get rid of the globals, and instead we'll put the current 'parse state' into a JavaScript object with at least two attributes: parseText and textPos.&lt;br /&gt;&lt;br /&gt;Then we pass that object to the relevant routines using a parameter - say 'parseState'. &lt;br /&gt;&lt;br /&gt;This way it becomes immediately clear to the human reader of the script which routines access that data (they need the parameter) and which ones don't access that data (they don't need the parameter) - it's a self-enforcing cleanup. From this moment on, each function that needs access to that data does 'advertise' the fact via its parameter list.&lt;br /&gt;&lt;br /&gt;Imagine every JavaScript function as a gob of code floating in space. Then imagine what outside factors influence the function's operation and how, in return, the function influences its environment. There are the parameters coming in at the top, the return value coming out at the bottom. Most of the time these two relations are pretty easy to see. &lt;br /&gt;&lt;br /&gt;Then there are any global variables that are modified or consulted by the function - using globals leaves a lot of room for unseen interaction between the function and its environment. Things like app.something and $.something are also globals - they are provided by InDesign, but they are still globals.&lt;br /&gt;&lt;br /&gt;The more 'isolated' you can make your functions, the easier it will be to re-use in a different script. &lt;br /&gt;&lt;br /&gt;Functions that interact with global data are like a beating heart - very difficult to transplant because there is a lot of stuff to disconnect and reconnect.&lt;br /&gt;&lt;br /&gt;Functions that take data via their parameters, and return data via their return value and/or via some of their parameters are much easier to transplant: a few easy connections to their environment; they easily snap in and out. &lt;br /&gt;&lt;br /&gt;&lt;h3&gt;5) Each function should do one thing well&lt;/h3&gt;&lt;br /&gt;We always try to create functions that do one thing well; during the 'frantic' phase of a project we often end up with functions that do lots of stuff. These multi-headed monsters need to be divvied up into smaller functions - each doing just one thing. Functions that are initially called something like 'ImportFileAndColorFramesAndDeleteOverrun' are split up into multiple smaller functions.&lt;br /&gt;&lt;br /&gt;This increases the chances of making things re-usable - any 'good' function eventually ends up in our growing function library and will be reused, which cuts down our development time on future projects. Multi-headed monsters are never reusable - so cutting them up has distinct advantages.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;6) Name constants and move them to the header of the file for easier customization&lt;/h3&gt;&lt;br /&gt;During the trial and error phase, you'll typically add all kinds of literal constants to the code - it is worthwhile to try and isolate these constants from the code and move them to a seaparate section near the top. &lt;br /&gt;&lt;br /&gt;This makes the script easier to adjust, and it also makes it more robust. &lt;br /&gt;&lt;br /&gt;Now, if a certain string constant is used twice in the script, there seems to be little advantage to creating a symbolic constant for the string and then use the constant instead of the literal string. Many people think this is a pedantic use of constants - on cursory inspection, the two approaches look not all that different.&lt;br /&gt;&lt;br /&gt;However, the advantage is that with a symbolic constant, typing errors can be immediately caught by the computer, whereas with literal strings the computer would not know that these two strings are supposed to be equal. &lt;br /&gt;&lt;br /&gt;So, if you'd type two literal strings "TextFrame" and "TextFrome", the computer would accept that - but if you typed two symbolic constants kTextFrame and kTextFrome, the second one would be undefined and cause an error.&lt;br /&gt;&lt;br /&gt;By clicking the link provided in this sentence, you can download a real-life example of a small script being refactored, from experimental form to a cleaner form - click &lt;a href="http://www.rorohiko.com/podcast/JitterScripts.zip"&gt;here&lt;/a&gt; to download &lt;a href="http://www.rorohiko.com/podcast/JitterScripts.zip"&gt;JitterScripts.zip&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1401434775260820755-7920773274453138684?l=rorohiko.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=A6L7C7Y2"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=v7RfGwFB"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=42" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=aFBqF9EM"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=gCcyZ8bm"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?i=gCcyZ8bm" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=yX2V5HK8"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=dhARJ6lW"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?i=dhARJ6lW" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=giZ5oEca"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?i=giZ5oEca" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=oASB7EyO"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=134" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rorohiko/~4/8YFEPp-n6vM" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2007-12-07T17:09:39.299-08:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><media:content url="http://feedproxy.google.com/~r/Rorohiko/~5/Oaz6Ko4cPvQ/JitterScripts.zip" fileSize="86370" type="application/zip" /><itunes:explicit>no</itunes:explicit><itunes:subtitle>Today we'll talk about cleaning up scripts, and as a bonus, we'll work on a script that adds a 'hand-written' quality to text: changing something like this: into By clicking the link provided in this sentence, you can download this real-life example of a </itunes:subtitle><itunes:author>Kris Coppieters</itunes:author><itunes:summary>Today we'll talk about cleaning up scripts, and as a bonus, we'll work on a script that adds a 'hand-written' quality to text: changing something like this: into By clicking the link provided in this sentence, you can download this real-life example of a small script being refactored, from experimental form to a cleaner form - click here to download JitterScripts.zip Listen to or read the podcast transcript for more info... On to the podcast - click here to listen to it! So, the script works, everyone is happy - but maybe you are not done yet... Imagine that you will have to pick that same script up again twelve months from now. How much time will it take you to 'get back up to speed' and rebuild a mental picture of the script and what it is doing? Probably it will take you many hours of browsing, debugging and fiddling around before you regain enough understanding of the script's inner workings to make a 'safe' change. Now, what if the circumstances have changed, and the script needs to be adjusted to cope with a new environment - it might need to be moved from InDesign to InDesign Server, there might be new requirements... How about spending some time now - when your head is still filled with knowledge about how it all works - and make sure the script becomes more future-proof. In this podcast, I'll list a few of the techniques I personally use to 'future-proof' my scripts. Before diving into the techniques, I need to explain how we approach ExtendScript development here at Rorohiko; we've adapted an approach that delivers very good quality at a reasonable price - we're not cheap, but as opposed to many other custom developments, our solutions work and work well. When we're developing custom scripts, we use a 'no cure, no pay' approach, for a number of reasons. The main reason is, that for this type of development, building a sufficiently accurate quote often costs us more than the development itself. For an accurate quote, we would first and foremost need an accurate, extensive project brief. But in our business we're often dealing with creative, fairly a-technical people, and we invariably found it very hard, even impossible to zoom in on an accurate enough technical description of the functionality being looked for. On top of that, what we're asked to do is often at odds with what is really needed. We're often asked to develop a specific solution, rather than being asked to solve a problem. From experience we've learned that it pays to dig deeper, and try and find out what the underlying problem is - quite often the asked-for 'solution' only cures a symptom, and leaves the underlying problem unfixed. The most efficient way we found to get the technical information we need from creative people is to use an iterative approach. Instead nagging people and trying to wring a technical brief out of them, we put the cart before the horse instead, and we create something, anything, as good as we can, based on the still limited understanding we have of the problem at hand. We present our customer with the attempted solution, and get their feedback - it is much easier for them to explain what is wrong or what is missing from some tangible, real software, rather than trying to come up with blueprint. Based on the feedback, we adjust the solution (or throw it out and start over), and we go through a few iterations, until we have the thing sussed. Eventually, we reach a good, smooth solution, and by that time we also know exactly what the cost of that solution is. At that point, the 'no cure, no pay' system kicks in: our customer can choose to purchase and continue to use the software, or alternatively, in case our solution were to not live up to its promise, the software is simply destroyed, and there is no cost to the customer. This approach works really well, but the successive iterations cause the software to go through a few swings and roundabouts, and along the way, grow a whole collection of warts if we're not careful. We'll typ</itunes:summary><itunes:keywords>printing,prepress,automation,InDesign,Adobe,CS,CS2,CS3,Rorohiko,plug,in,plugin,software,consultancy,design,desktop,publishing,PDF,Acrobat,XPress,QuarkXPress,XTension</itunes:keywords><feedburner:origLink>http://rorohiko.blogspot.com/2007/12/lightning-brain-podcast-click-here-to.html</feedburner:origLink><enclosure url="http://feedproxy.google.com/~r/Rorohiko/~5/Oaz6Ko4cPvQ/JitterScripts.zip" length="86370" type="application/zip" /><feedburner:origEnclosureLink>http://www.rorohiko.com/podcast/JitterScripts.zip</feedburner:origEnclosureLink></item><item><title>Virtual Group</title><link>http://feedproxy.google.com/~r/Rorohiko/~3/s2opSIJ5Ju4/virtual-group.html</link><author>kris@rorohiko.com (Kris Coppieters)</author><pubDate>Sun, 11 Nov 2007 23:04:53 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-1401434775260820755.post-5148036938357878975</guid><description>In addition to being a software developer and trainer, I am also a &lt;a href="http://www.virtual.co.nz/index.php/KrisCoppieters/KrisCoppieters" target="_blank"&gt;member&lt;/a&gt; of a New Zealand-based team of business consultants, called the '&lt;a href="http://www.virtual.co.nz/" target="_blank"&gt;Virtual Group&lt;/a&gt;'. To better explain what the Virtual Group can do for an organisation, we'll be conducting a number of interviews with our team members.&lt;br /&gt;&lt;br /&gt;The first interviewee is &lt;a href="http://www.virtual.co.nz/index.php/BruceHolland/BruceHolland" target="_blank"&gt;Bruce Holland&lt;/a&gt; - Bruce is an expert in revitalising large mature organisations.&lt;br /&gt;&lt;br /&gt;I interviewed him today, and started a new &lt;a href="http://virtualgroupnz.blogspot.com/" target="_blank"&gt;Virtual Group blog/podcast&lt;/a&gt; which can be read and listened to by clicking &lt;a href="http://virtualgroupnz.blogspot.com/" target="_blank"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1401434775260820755-5148036938357878975?l=rorohiko.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=vUbMvDJC"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=g832OjD9"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=42" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=4b9QRqk8"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=BIr8I9fp"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?i=BIr8I9fp" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=BDFbwUeR"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=OdmQ4KkY"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?i=OdmQ4KkY" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=ip9TJBMG"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?i=ip9TJBMG" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=GXP8jH9x"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=134" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rorohiko/~4/s2opSIJ5Ju4" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2007-11-11T23:04:53.192-08:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://rorohiko.blogspot.com/2007/11/virtual-group.html</feedburner:origLink></item><item><title>Lightning Brain Podcast: Click here to listen to "InDesign User Interfaces"</title><link>http://feedproxy.google.com/~r/Rorohiko/~3/8AjYe4G4L14/lightning-brain-podcast-click-here-to.html</link><author>kris@rorohiko.com (Kris Coppieters)</author><pubDate>Mon, 29 Oct 2007 21:15:26 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-1401434775260820755.post-2300127494032478657</guid><description>Welcome to another episode of the Lightning Brain Podcast. We'll talk a little bit about InDesign and user-interface code.&lt;br /&gt;&lt;br /&gt;When it comes to extending InDesign, there are many options available: you could create a C++-based plug-in, you can create an ExtendScript (JavaScript) solution, you can build an AppleScript or VBScript-based solution, you can build a Flash-based UI and then use it in InDesign, you can glue some other development environment 'into' InDesign, and you can also make a hybrid of the aforementioned solutions...&lt;br /&gt;&lt;br /&gt;Which approach to choose depends on what your need is, what portion of the project is user-interface functionality as opposed to faceless functionality, what development environments you're familiar with, what your potential users are willing to accept, what budgets (time, money, resources, people, testers,...) are available for the project, what the politics involved are,... As in all things automation, there is no single 'best' solution - it all depends.&lt;br /&gt;&lt;br /&gt;In this podcast I want to describe an approach we've very successfully used for a few real-size, real-life projects, and what the advantages and disadvantages are.&lt;br /&gt;&lt;br /&gt;I first want to include a little disclosure: Rorohiko resells the &lt;a href="http://www.rorohiko.com/activepageitemsdeveloper.html"&gt;&lt;span style="font-style: italic;"&gt;Active Page Items Developer&lt;/span&gt;&lt;/a&gt; product as a commercial solution, and Active Page Items is very much part of the approach described here - so you might think this is podcast is a veiled advertisement for Active Page Items. Well, it is - but you have to keep in mind that Active Page Items has been created and has grown out of our own need for such a tool - Active Page Items was first; commercializing it came later.&lt;br /&gt;&lt;br /&gt;One of the things we've learned is that C++ development for InDesign can be quite expensive: simple principles and algorithms often take a surprising amount of code to express. I'd describe C++ development around InDesign as 'fluffy'. High-level concepts and patterns result in lots of classes and source code files and fairly large amounts of C++ code, much of which is often quite repetitive in a number of respects. Especially the development of user interface elements takes a lot of doing.&lt;br /&gt;&lt;br /&gt;At present, the only way to currently get a really 'native' InDesign UI look is to use C++ - e.g. if you want to create floating palettes, with all their end-user flexibility (tearing off, parking to the side,...) you need to use C++.&lt;br /&gt;&lt;br /&gt;From a UI perspective, C++ might be 'perfect', but often there are other approaches that could be classified as 'good enough'. They might not look as nice, but they might do the job.&lt;br /&gt;&lt;br /&gt;For example, using ExtendScript with InDesign CS3 one can develop quite complex user interfaces which often are 'good enough'. ExtendScript development is easily an order of magnitude cheaper than C++ development - so if the parameters of the project at hand don't require an absolute perfect-looking interface with floating palettes, ExtendScript can be the way to go.&lt;br /&gt;&lt;br /&gt;Often there are also user-interfaces that need something a little bit more complex than what can be accomplished using ExtendScript, yet don't need a full blown native InDesign user interface. That's where the 'hybrid' approach that we've been using comes in.&lt;br /&gt;&lt;br /&gt;The approach we've chosen basically boils down to: REALbasic, Active Page Items, ExtendScript.&lt;br /&gt;&lt;br /&gt;We create our more complex user interfaces in REALbasic. However, this is not an absolute requirement - on the whole, we might have used Java instead.&lt;br /&gt;&lt;br /&gt;The main reasons for choosing REALbasic over Java are 1) that it allows us to create cross-platform code that looks sligthly more 'native' on Mac as well as on Windows 2) easy access to global floating windows (both on Mac and Windows) and 3) purely personal preference: I find I personally can build and implement user-interfaces faster with REALbasic than with Java.&lt;br /&gt;&lt;br /&gt;Easy access to global floating windows is one feature of REALbasic that comes in really handy, for which I don't know whether Java offers an easy alternative.&lt;br /&gt;&lt;br /&gt;Global floating windows are windows that remain 'on top', even if the application that owns them is not the foreground application. This is fairly important for the illusion we want to maintain.&lt;br /&gt;&lt;br /&gt;Active Page Items is a fairly large C++ plug-in, which we extend as we need with new functionality.&lt;br /&gt;&lt;br /&gt;One of its many functions is coordinating InDesign with external applications. Through Active Page Items, we are able to create an illusion that makes the external 'satellite' apps seem to be part of InDesign.&lt;br /&gt;&lt;br /&gt;One of the tricks is to 'lock' InDesign in a modal mode while one of our REALbasic satellite apps is running. That creates the illusion that a dialog owned by the satellite app seems to belong to InDesign.&lt;br /&gt;&lt;br /&gt;However, the modal mode is not real - it's a simulated modal mode, and while this simulated modal mode is active, InDesign is actually still very much 'alive' and able to execute ExtendScript code - so it is possible to create a 'live' session between the satellite app and InDesign while the user interacts with this 'simulated modal dialog', while 'locking out' the user from any undesirable interactions with InDesign.&lt;br /&gt;&lt;br /&gt;The illusion is not perfect: on the Mac's Dock and on the Windows start bar it is fairly apparent some secondary app is running, but that is a cosmetic issue, and it does not really seem to annoy our end-users too much.&lt;br /&gt;&lt;br /&gt;- Active Page Items is also used to manage menu items and context menu items. This is mostly because our solutions needed to support CS2 as well as CS3 - InDesign CS3's ExtendScript has all you need to create menu items and context menus, so if you have the luxury of an InDesign-CS3-only setup, you can stick with standard ExtendScript in that respect.&lt;br /&gt;&lt;br /&gt;- For communication between the various disparate components, we use temporary files. This is a very low-tech and crude approach, but it works 'well enough'. In a future version of Active Page Items we might add support for a more 'high-tech' information exchange mechanism, but for now temp files do us just fine.&lt;br /&gt;&lt;br /&gt;If you want to try things out for yourself, I've created a very small sample of such a hybrid solution; the source code to it comes as part of our Active Page Items Developer Toolkit. If you download the latest demo version of the Toolkit from our web site, you'll find my example code tucked away amongst the other examples.&lt;br /&gt;&lt;br /&gt;Some of the scripts can also be viewed at the end of the blog entry.&lt;br /&gt;&lt;br /&gt;The sample, which deals with overset text, has no real practical applications as such, but you should be able to see how it can be made into a practical solution for particular problems.&lt;br /&gt;&lt;br /&gt;The sample performs the following function: it looks out for overset text. As soon as a text frame gets overset, some ExtendScript code jumps into action, and fires up an external application, which then shows the contents of the text frame in a scrolling text field. The idea is that the user edits the text down to a shorter version to stop the overset. Of course, is not a practical approach at all, but it does allow us to demonstrate the various techniques involved.&lt;br /&gt;&lt;br /&gt;In the sample, the active bit of ExtendScript code is currently 'attached' to a 'dummy' page item that sits on the pasteboard. The page item is not meant to be printed or have any sensibly printable content; all it does is hold some script code. We call such a page item a 'controller'. The controller 'watches' one or more page items, and waits for the events to occur.&lt;br /&gt;&lt;br /&gt;In a 'real' solution based on Active Page Items, we'd instead 'package' that script code into a so-called 'Scripted Plug-in', in a .spln file.&lt;br /&gt;&lt;br /&gt;In this particular case the controller is set to watch all page items, and the  'interesting events' it might watch out for are&lt;br /&gt;&lt;br /&gt;- an event called 'subjectModified-recomposed-overset' which occurs when any page item ends up being overset after something happened to it (user typed something, frame resized,...)&lt;br /&gt;&lt;br /&gt;- an event called 'idle' which occurs at regular intervals. In this particular solution, we rarely look out for 'idle' events as to not unnecessarily tax the computer's performance. We only do so while InDesign is in 'simulated modal mode' when the satellite application is running.&lt;br /&gt;&lt;br /&gt;So, when any page item becomes overset, the subjectModified-recomposed-overset event is captured by the controller.&lt;br /&gt;&lt;br /&gt;The controller's ExtendScript then launches the external satellite application using a special Active Page Items method attached to the application object - app.launchWith().&lt;br /&gt;&lt;br /&gt;app.launchWith() has a number of functions. The most common use is as an extension to the File.execute() method.&lt;br /&gt;&lt;br /&gt;File.execute() is similar to double-clicking an icon in Explorer or in the Finder, and will pick the default application to open a particular document.&lt;br /&gt;&lt;br /&gt;app.launchWith() allows you to designate a particular application to open a particular document with - it is more akin to drag-dropping a document file icon onto an application's icon.&lt;br /&gt;&lt;br /&gt;On top of that, app.launchWith() has a special feature - it allows us to lock InDesign into simulated modal model for as long as the launched application continues to run.&lt;br /&gt;&lt;br /&gt;That makes for a crude, yet effective way to synchronize a satellite app with InDesign: you launch the satellite application using app.launchWith(), and when the user clicks 'OK' in the dialog presented by the satellite application, the application simply exits. Active Page Items is monitoring the satellite app, and as soon as it sees it exit, it will release the simulated modal lock.&lt;br /&gt;&lt;br /&gt;So, the controller's ExtendScript first writes the contents of the overset frame into a temporary text file.&lt;br /&gt;&lt;br /&gt;It then uses app.launchWith() to tell the satellite app to open this temp text file and pick up the data being communicated.&lt;br /&gt;&lt;br /&gt;The satellite app then runs until the user clicks OK in the dialog, after which it writes the new data to the same temporary text file. When the application exits, Active Page Items will release the simulated modal lock automatically.&lt;br /&gt;&lt;br /&gt;While the satellite app is running and InDesign is in simulated modal mode, the controller is catching idle events (roughly once per second). During these events, we could perform more communication backwards and forwards with the satellite application (e.g. for live previews or so), but in this case, all we do is check the simulated modal lock: as long as that is not lifted, we know the app is still running and we do nothing.&lt;br /&gt;&lt;br /&gt;When we notice that the simulated modal lock has disappeared upon receiving one of the idle events, we know it the user has clicked OK, the app has written the new data to the temp file, and has quit, and we know we can now read the returned data, and then we can stop looking for idle events - things come back to normal, with the controller only watching out for overset events.&lt;br /&gt;&lt;br /&gt;This sample should give you a little bit of insight on how we approached some real-live projects with very good results.&lt;br /&gt;&lt;br /&gt;The advantages we had were:&lt;br /&gt;- fast development of a good-looking UI that was beyond what can be accomplished with ExtendScript.&lt;br /&gt;- cross-platform (Mac &amp;amp; Win) support: the same code works on both platforms only minute amounts of conditional code.&lt;br /&gt;&lt;br /&gt;The disadvantages:&lt;br /&gt;- don't pay attention to the man behind the curtain. Global floating windows and simulated modal mode allow you to get close, but nothing identical to the real thing (an InDesign-generated dialog or palette). The satellite app is visible - we worked around that by giving it a good-looking icon.&lt;br /&gt;&lt;br /&gt;On the whole, the disadvantages were acceptable for the particular projects, and as a result we were able to offer very high efficiency in realizing these projects.&lt;br /&gt;&lt;br /&gt;Thanks for your attention!&lt;br /&gt;&lt;br /&gt;---&lt;br /&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;//&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// Example of using an external program for dialogs.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;//&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// This document needs a file called "ExampleInDesignSatellite.app" (on Mac)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// or "ExampleInDesignSatellite.exe" (on Windows) in the same folder&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// as the document.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;//&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// This event handler handles subjectModified-recomposed-overset and&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// idle events.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;//&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// In normal circumstances, the event filter is set to just &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// subjectModified-recomposed-overset - i.e. the handler only &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// activates when there is a text frame that has just recomposed,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// and shows overset&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;//&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// When that happens, the handler below will launch an external&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// program to edit the text frame contents, and also change the event&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// filter to "idle" - causing repeated calls to this handler while&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// the user is editing the text in the external program. The &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// external program is launched using launchWith and a mode equal&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// to 4 - meaning: InDesign is modal locked for the user until the&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// external program terminates.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;//&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// So, what happens is that we repeatedly receive and handle&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// idle events, until app.callExtension(0x90b6C,10003) returns&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// false (meaning: not modal locked), which only happens when&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// the external program has terminated.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;//&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// As soon as the external program terminates, we restore the &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// normal event filter, and read the output of the external &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// program to stuff into the text frame&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;//&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;do&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  //&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  // tempFile is used to communicate data to and from the&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  // external program&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  //&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  var tempFile = File(Folder.temp + "/tempText.txt");&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  //&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  // Check if we're in the "idle" phase - waiting for the external&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  // program to finish&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  //&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  if (theItem.eventCode == "idle")&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   //&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   // We check whether InDesign is still modal locked. If so, then&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   // the external program has not finished yet - bail out of the event&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   // handler. In a second or so, on the next idle event, we'll give&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   // it another go&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   //&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   var indesignModalLocked = app.callExtension(0x90b6C,10003);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   if (indesignModalLocked)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     break;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   //&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   // The modal lock is gone - so the external program is finished.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   // We restore the event filter to what it was before it all started&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   //&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   theItem.eventFilter = "subjectModified-recomposed-overset";&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   //&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   // Did the external program communicate some data back to us?&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   // If so, then it is in the temporary file&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   //&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   if (! tempFile.exists)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     break;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   //&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   // Read the edited text and stuff it back into the story being edited&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   // We've stored a reference to the story in the data store associated to&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   // theItem&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   //&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   tempFile.open("r");&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   var editedStory = theItem.getDataStore("editedStory");&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   editedStory.contents = tempFile.read();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   tempFile.close();&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   //&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   // And we're done for now!&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   //&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   break;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  //&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  // Ok, we're handling a subjectModified-recomposed-overset event here.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  //&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  var theDocument = GetParentDocument(theItem);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  //&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  // We need the document's path to find the satellite app. If the document&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  // has not been saved yet, there is no path - so bail out&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  //&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  if (! theDocument.saved)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    break;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  //&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  // Is this a Mac or a PC? The Mac uses .app files, the PC uses .exe&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  //&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  var isMac = $.os.charAt(0) == "M";&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  if (isMac)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    var theSatelliteApp = File(theDocument.fullName.parent + "/ExampleInDesignSatellite.app");&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  else&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    var theSatelliteApp = File(theDocument.fullName.parent + "/ExampleInDesignSatellite.exe");&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  //&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  // If we cannot find the satellite app, bail out&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  //&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  if (! theSatelliteApp.exists)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    break;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  //&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  // Write the overset story to a temporary text file&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  //&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  var theStory = theItem.eventSource.parentStory;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  tempFile.open("w");&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  tempFile.write(theStory.contents);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  tempFile.close();&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  //&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  // If we cannot find the temp file we just created, bail out&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  //&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  if (! tempFile.exists)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    break;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  //&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  // Open the temp file with the satellite app, and use flag "4"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  // which means: lock InDesign into a user-modal mode until&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  // the satellite app terminates&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  //&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  app.launchWith(tempFile.fsName,theSatelliteApp.fsName,4);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  //&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  // Change the event filter to process idle events - so we&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  // can regularly check whether the satellite app has &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  // terminated or not&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  //&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  theItem.eventFilter = "idle";&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  //&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  // We need to remember the story so we can put the edited&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  // text somewhere later on&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  //&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  theItem.setDataStore("editedStory",theStory);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;while (false);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// End of event handler. Utility functions below&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;function GetParentDocument(pageItem)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  var document = null;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  do&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    var err;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    try&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      document = pageItem.parent;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    catch(err)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      document = null;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    if (document == null)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      break;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    if (document instanceof Document)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      break;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    if (document == pageItem)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      document = null;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      break;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    pageItem = document;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  while (true);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  return document;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1401434775260820755-2300127494032478657?l=rorohiko.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=AfX7TpAd"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=Vuj9siqM"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=42" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=gzQLOsg5"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=bUoRqHxT"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?i=bUoRqHxT" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=k40Thpie"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=hI6V3XFs"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?i=hI6V3XFs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=vc9Bkz40"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?i=vc9Bkz40" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=aTqXMsdy"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=134" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rorohiko/~4/8AjYe4G4L14" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2007-10-29T21:15:26.802-07:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><media:content url="http://feedproxy.google.com/~r/Rorohiko/~5/icBEZPA7U5o/InDesignUICoding.mp3" fileSize="5410955" type="audio/mpeg" /><itunes:explicit>no</itunes:explicit><itunes:subtitle>Welcome to another episode of the Lightning Brain Podcast. We'll talk a little bit about InDesign and user-interface code. When it comes to extending InDesign, there are many options available: you could create a C++-based plug-in, you can create an Exten</itunes:subtitle><itunes:author>Kris Coppieters</itunes:author><itunes:summary>Welcome to another episode of the Lightning Brain Podcast. We'll talk a little bit about InDesign and user-interface code. When it comes to extending InDesign, there are many options available: you could create a C++-based plug-in, you can create an ExtendScript (JavaScript) solution, you can build an AppleScript or VBScript-based solution, you can build a Flash-based UI and then use it in InDesign, you can glue some other development environment 'into' InDesign, and you can also make a hybrid of the aforementioned solutions... Which approach to choose depends on what your need is, what portion of the project is user-interface functionality as opposed to faceless functionality, what development environments you're familiar with, what your potential users are willing to accept, what budgets (time, money, resources, people, testers,...) are available for the project, what the politics involved are,... As in all things automation, there is no single 'best' solution - it all depends. In this podcast I want to describe an approach we've very successfully used for a few real-size, real-life projects, and what the advantages and disadvantages are. I first want to include a little disclosure: Rorohiko resells the Active Page Items Developer product as a commercial solution, and Active Page Items is very much part of the approach described here - so you might think this is podcast is a veiled advertisement for Active Page Items. Well, it is - but you have to keep in mind that Active Page Items has been created and has grown out of our own need for such a tool - Active Page Items was first; commercializing it came later. One of the things we've learned is that C++ development for InDesign can be quite expensive: simple principles and algorithms often take a surprising amount of code to express. I'd describe C++ development around InDesign as 'fluffy'. High-level concepts and patterns result in lots of classes and source code files and fairly large amounts of C++ code, much of which is often quite repetitive in a number of respects. Especially the development of user interface elements takes a lot of doing. At present, the only way to currently get a really 'native' InDesign UI look is to use C++ - e.g. if you want to create floating palettes, with all their end-user flexibility (tearing off, parking to the side,...) you need to use C++. From a UI perspective, C++ might be 'perfect', but often there are other approaches that could be classified as 'good enough'. They might not look as nice, but they might do the job. For example, using ExtendScript with InDesign CS3 one can develop quite complex user interfaces which often are 'good enough'. ExtendScript development is easily an order of magnitude cheaper than C++ development - so if the parameters of the project at hand don't require an absolute perfect-looking interface with floating palettes, ExtendScript can be the way to go. Often there are also user-interfaces that need something a little bit more complex than what can be accomplished using ExtendScript, yet don't need a full blown native InDesign user interface. That's where the 'hybrid' approach that we've been using comes in. The approach we've chosen basically boils down to: REALbasic, Active Page Items, ExtendScript. We create our more complex user interfaces in REALbasic. However, this is not an absolute requirement - on the whole, we might have used Java instead. The main reasons for choosing REALbasic over Java are 1) that it allows us to create cross-platform code that looks sligthly more 'native' on Mac as well as on Windows 2) easy access to global floating windows (both on Mac and Windows) and 3) purely personal preference: I find I personally can build and implement user-interfaces faster with REALbasic than with Java. Easy access to global floating windows is one feature of REALbasic that comes in really handy, for which I don't know whether Java offers an easy alternative. Global floating windows are windows that rem</itunes:summary><itunes:keywords>printing,prepress,automation,InDesign,Adobe,CS,CS2,CS3,Rorohiko,plug,in,plugin,software,consultancy,design,desktop,publishing,PDF,Acrobat,XPress,QuarkXPress,XTension</itunes:keywords><feedburner:origLink>http://rorohiko.blogspot.com/2007/10/lightning-brain-podcast-click-here-to.html</feedburner:origLink><enclosure url="http://feedproxy.google.com/~r/Rorohiko/~5/icBEZPA7U5o/InDesignUICoding.mp3" length="5410955" type="audio/mpeg" /><feedburner:origEnclosureLink>http://www.rorohiko.com/mp3/InDesignUICoding.mp3</feedburner:origEnclosureLink></item><item><title>Going overseas</title><link>http://feedproxy.google.com/~r/Rorohiko/~3/Ka4pnVx_0XY/going-overseas.html</link><author>kris@rorohiko.com (Kris Coppieters)</author><pubDate>Wed, 22 Aug 2007 00:33:29 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-1401434775260820755.post-718311523562737869</guid><description>The next podcast will be a bit delayed - I am travelling to Europe to run some developer trainings, and I have not had the time to get my next podcast done. Stay tuned!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1401434775260820755-718311523562737869?l=rorohiko.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=hHoXmMx6"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=QNpTiNX2"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=42" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=lVVIbFRf"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=WOdK96SJ"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?i=WOdK96SJ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=lbDRkTN8"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=6CKdduuQ"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?i=6CKdduuQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=cm9GzzyZ"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?i=cm9GzzyZ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=4Ko2G7tY"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=134" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rorohiko/~4/Ka4pnVx_0XY" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2007-08-22T00:33:29.767-07:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://rorohiko.blogspot.com/2007/08/going-overseas.html</feedburner:origLink></item><item><title>Lightning Brain Podcast: Click here to listen to "Writing code like a story"</title><link>http://feedproxy.google.com/~r/Rorohiko/~3/oepRQ2wFqkk/lightning-brain-podcast-click-here-to.html</link><author>kris@rorohiko.com (Kris Coppieters)</author><pubDate>Tue, 07 Aug 2007 19:27:23 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-1401434775260820755.post-5738701660288444843</guid><description>Book mentioned in podcast:&lt;br /&gt;&lt;br /&gt;Code Craft&lt;br /&gt;The practice of writing excellent code&lt;br /&gt;by Pete Goodliffe&lt;br /&gt;ISBN 1-59327-119-0&lt;br /&gt;&lt;br /&gt;Rough transcript of podcast:&lt;br /&gt;&lt;br /&gt;Writing code like a story&lt;br /&gt;&lt;br /&gt;Hi, my name is Kris Coppieters from Rorohiko. This is the third Lightning Brain podcase - writing code like a story.&lt;br /&gt;&lt;br /&gt;I've been programming for over 30 years now - and my programming style has changed over time, to suit new languages, to suit new ideas, to suit programming styles.&lt;br /&gt;&lt;br /&gt;If I look back at code I wrote, say, ten years ago, the changes are not all that great when compared to code I wrote earlier; I seem to have settled into a number of habits that work well, and have not felt much need to change.&lt;br /&gt;&lt;br /&gt;Many of the things I do also seem to coincide with the advice given in many books about coding style - most of it is common sense.&lt;br /&gt;&lt;br /&gt;I want to make it clear that some of my preferences are just that - preferences; sometimes, as a coder, you get 'locked in' to a certain approach. There are often many other approaches that are at least as valid, but there is no clear benefit to switch between them, so you stay 'locked' into a particular way of doing things. &lt;br /&gt;&lt;br /&gt;When I was younger, I would let myself be enticed into endless debates - things like where to put the braces {} and whether to use tabs or spaces, that kind of stuff. &lt;br /&gt;&lt;br /&gt;Through experience, I've learned that those things are highly irrelevant. I have found that consistency is more important rather than what your are consistent in. &lt;br /&gt;&lt;br /&gt;So, if you like the braces one way or another, you won't get any argument from me. But you will get an argument if your braces are sprinkled one way here, another way there. To me that's a bit the same as having to read a book where the font size jumps up and down at random: it makes reading the stuff harder for no reason.&lt;br /&gt;&lt;br /&gt;I often have to work on other people's code - and currently, my approach is to follow whatever consistent coding convention is used in each individual source file. I have no trouble with a project that consists of source files created by individuals who all had different ideas on how to structure their code - as long as there is a consistency to it within each source code file.&lt;br /&gt;&lt;br /&gt;I know of developers that cannot stand working on source code that is not exactly structured 'their' way. I consider such inability a major disadvantage: these people tend to waste large amounts of time on 'restructuring' some perfectly consistent piece of code.&lt;br /&gt;&lt;br /&gt;I strive to write code with as few comments as possible. Yes - you heard that right. I think comments are a last-resort type of thing. &lt;br /&gt;&lt;br /&gt;I try to write the code first and foremost in such a way that it is as clear and as easy to understand as possible; I think this might be more of an art than a technique. &lt;br /&gt;&lt;br /&gt;I only use comments if I cannot make everything crystal clear by means of clean code. You do need as little comments as possible, but no less. Gratuitous comments that simply re-state what the code does are a no-no - things like:&lt;br /&gt;&lt;br /&gt;// Increment i&lt;br /&gt;i++;&lt;br /&gt;&lt;br /&gt;// This is the constructor&lt;br /&gt;&lt;br /&gt;make me cringe.&lt;br /&gt;&lt;br /&gt;Comments are dangerous - they have a tendency to get outdated as the code around them evolves, and instead of being helpful, they often become a liability. So it is important to try hard to make the code so clear it does not need comments.&lt;br /&gt;&lt;br /&gt;Instead, I restructure and rewrite my code until it is as close to self-explanatory as possible.&lt;br /&gt;&lt;br /&gt;My priorities are always to write readable and understandable code first, and efficient code second. When someone else (often me) needs to pick up the code in a few months or years, the most important goal is to make it easy on the developer to grasp the meaning of the code. Not doing so is inviting bugs to be introduced during maintenance by a developer who only half-grasps or half-remembers what is going on. &lt;br /&gt;&lt;br /&gt;Often, if the code cannot be made self-explanatory, that is a symptom that something is fundamentally wrong with the approach used, and you need to take a step back and rethink things.&lt;br /&gt;&lt;br /&gt;Writing good code is almost the same as writing a good book or a good story: it has good content, is easy to understand, is consistent in as many respects as possible, is nicely laid out. Code also needs those traits.&lt;br /&gt;&lt;br /&gt;I also pay a lot of attention to the code layout and neatness. Small example: I will often order all of the functions, procedures and declarations and alike in alphabetical order. &lt;br /&gt;&lt;br /&gt;I know that many IDEs make it easy to 'jump' around to functions in a source code file - but sometimes I find myself separated from my finely honed development environment, working in an unfamiliar debugger, or staring at my source code in printed form, or using WordPad to view the code. Having everything alphabetical makes it easy to guess which direction to scroll to find something in the source code.&lt;br /&gt;&lt;br /&gt;Just recently I also figured out a way to describe how I like to pick names for things. &lt;br /&gt;&lt;br /&gt;One basic rule of thumb is: short scope allows short names. For example, if I need an index variable, and it will be needed for just two or three lines, I am perfectly happy to call it 'idx' or even 'i'. If the scope gets larger, and spans a few tens of lines, I will make the index name more descriptive - for example 'spreadIdx' or 'pageIdx'. If there are similar variables around, I find what sets them apart and name them accordingly, making sure they are not easily confused - unless in rare circumstances, I'll never use variables like 'idx' and 'idx2'.&lt;br /&gt;&lt;br /&gt;Names that have large scope (e.g. span multiple source files) are often longer, and often tell a little story (but again - not too long; it's easy to go overboard).&lt;br /&gt;&lt;br /&gt;When creating names, I also try to be consistent in how a name gets formed, and I will often build name that first states the more general and then the more specific. &lt;br /&gt;&lt;br /&gt;Similar names have a similar 'lead-in', so in case they get ordered alphabetically (e.g. in a debugger or some IDEs), similar things end up 'close to' other similar things. For example, I'll use&lt;br /&gt;&lt;br /&gt;const kFileName_Template = "bla.indt";&lt;br /&gt;const kFileName_MainDocument = "yaya.ind";&lt;br /&gt;&lt;br /&gt;instead of &lt;br /&gt;&lt;br /&gt;const kTemplate_FileName = "bla.indt";&lt;br /&gt;const kMainDocument_FileName  = "yaya.ind";&lt;br /&gt;&lt;br /&gt;Till next time!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1401434775260820755-5738701660288444843?l=rorohiko.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=6jdqUeXI"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=M1hmb1MX"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=42" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=5jCzqXEz"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=iQ1wPYF5"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?i=iQ1wPYF5" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=XrwgBgSQ"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=6IJABLsP"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?i=6IJABLsP" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=JxiPiSEn"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?i=JxiPiSEn" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=NOW2qktg"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=134" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rorohiko/~4/oepRQ2wFqkk" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2007-08-07T19:27:23.777-07:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><media:content url="http://feedproxy.google.com/~r/Rorohiko/~5/Niu0X5jrQBE/StoryCode.mp3" fileSize="2887638" type="audio/mpeg" /><itunes:explicit>no</itunes:explicit><itunes:subtitle>Book mentioned in podcast: Code Craft The practice of writing excellent code by Pete Goodliffe ISBN 1-59327-119-0 Rough transcript of podcast: Writing code like a story Hi, my name is Kris Coppieters from Rorohiko. This is the third Lightning Brain podcas</itunes:subtitle><itunes:author>Kris Coppieters</itunes:author><itunes:summary>Book mentioned in podcast: Code Craft The practice of writing excellent code by Pete Goodliffe ISBN 1-59327-119-0 Rough transcript of podcast: Writing code like a story Hi, my name is Kris Coppieters from Rorohiko. This is the third Lightning Brain podcase - writing code like a story. I've been programming for over 30 years now - and my programming style has changed over time, to suit new languages, to suit new ideas, to suit programming styles. If I look back at code I wrote, say, ten years ago, the changes are not all that great when compared to code I wrote earlier; I seem to have settled into a number of habits that work well, and have not felt much need to change. Many of the things I do also seem to coincide with the advice given in many books about coding style - most of it is common sense. I want to make it clear that some of my preferences are just that - preferences; sometimes, as a coder, you get 'locked in' to a certain approach. There are often many other approaches that are at least as valid, but there is no clear benefit to switch between them, so you stay 'locked' into a particular way of doing things. When I was younger, I would let myself be enticed into endless debates - things like where to put the braces {} and whether to use tabs or spaces, that kind of stuff. Through experience, I've learned that those things are highly irrelevant. I have found that consistency is more important rather than what your are consistent in. So, if you like the braces one way or another, you won't get any argument from me. But you will get an argument if your braces are sprinkled one way here, another way there. To me that's a bit the same as having to read a book where the font size jumps up and down at random: it makes reading the stuff harder for no reason. I often have to work on other people's code - and currently, my approach is to follow whatever consistent coding convention is used in each individual source file. I have no trouble with a project that consists of source files created by individuals who all had different ideas on how to structure their code - as long as there is a consistency to it within each source code file. I know of developers that cannot stand working on source code that is not exactly structured 'their' way. I consider such inability a major disadvantage: these people tend to waste large amounts of time on 'restructuring' some perfectly consistent piece of code. I strive to write code with as few comments as possible. Yes - you heard that right. I think comments are a last-resort type of thing. I try to write the code first and foremost in such a way that it is as clear and as easy to understand as possible; I think this might be more of an art than a technique. I only use comments if I cannot make everything crystal clear by means of clean code. You do need as little comments as possible, but no less. Gratuitous comments that simply re-state what the code does are a no-no - things like: // Increment i i++; // This is the constructor make me cringe. Comments are dangerous - they have a tendency to get outdated as the code around them evolves, and instead of being helpful, they often become a liability. So it is important to try hard to make the code so clear it does not need comments. Instead, I restructure and rewrite my code until it is as close to self-explanatory as possible. My priorities are always to write readable and understandable code first, and efficient code second. When someone else (often me) needs to pick up the code in a few months or years, the most important goal is to make it easy on the developer to grasp the meaning of the code. Not doing so is inviting bugs to be introduced during maintenance by a developer who only half-grasps or half-remembers what is going on. Often, if the code cannot be made self-explanatory, that is a symptom that something is fundamentally wrong with the approach used, and you need to take a step back and rethink things. Writing good code is almost th</itunes:summary><itunes:keywords>printing,prepress,automation,InDesign,Adobe,CS,CS2,CS3,Rorohiko,plug,in,plugin,software,consultancy,design,desktop,publishing,PDF,Acrobat,XPress,QuarkXPress,XTension</itunes:keywords><feedburner:origLink>http://rorohiko.blogspot.com/2007/08/lightning-brain-podcast-click-here-to.html</feedburner:origLink><enclosure url="http://feedproxy.google.com/~r/Rorohiko/~5/Niu0X5jrQBE/StoryCode.mp3" length="2887638" type="audio/mpeg" /><feedburner:origEnclosureLink>http://www.rorohiko.com/mp3/StoryCode.mp3</feedburner:origEnclosureLink></item><item><title>Lightning Brain Podcast: Click here to listen to "Fun with Drop Shadows in InDesign"</title><link>http://feedproxy.google.com/~r/Rorohiko/~3/rpOeifC2NZY/click-here-to-listen-to-fun-with-drop.html</link><author>kris@rorohiko.com (Kris Coppieters)</author><pubDate>Wed, 01 Aug 2007 21:54:24 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-1401434775260820755.post-1778732065555393093</guid><description>Example Files:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.rorohiko.com/podcast/ShadowDanceExampleFiles.zip"&gt;Click here to download sample script and sample document&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Example result:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.rorohiko.com/podcast/ShadowDance.png"&gt;&lt;br /&gt;&lt;br /&gt;Rough Transcript of Podcast:&lt;br /&gt;&lt;br /&gt;Hi, my name is Kris Coppieters from Rorohiko, and this is my second 'Lighting Brain' podcast - about having fun with drop shadows in InDesign.&lt;br /&gt;&lt;br /&gt;Initially, I'll try to create a number of podcasts in fairly quick succession, as to build up some content on the Rorohiko blog, but in the long run I aim to release a new podcast about once every two weeks.&lt;br /&gt;&lt;br /&gt;This episode I wanted to talk a bit about some fun experiments I did with drop shadows in InDesign. My brain seems to be a magnet for ideas - which would be fine, if only all ideas that pop up would be useful. Sadly enough, some of my ideas are rather silly, and this podcast is based on one of the silly ones.&lt;br /&gt;&lt;br /&gt;The podcast will also delve a little bit into some mathematical aspects of my experiments. However, even if you are not mathematically inclined you should still be able to have fun with the example document and example script - so even if the mathematics gives you the blue shivers, don't worry! Just download the sample files and have fun!&lt;br /&gt;&lt;br /&gt;My idea was this: assume there are a number of page items scattered over a page or spread. Why not coordinate all these drop shadows so they cause some visual effect to occur? Standard drop shadows are rather dull. They simulate what would happen if there was a light source at infinite distance throwing light on a page item floating at a particular height above the page.&lt;br /&gt;&lt;br /&gt;What I was wondering about was: what would happen if the simulated light source was not at infinite distance, but instead somewhere else - for example, located on the viewer's head, close to the paper, like a head-torch, or if the light source was simulating one of those swiveling desk lights.&lt;br /&gt;&lt;br /&gt;The other thing I wondered about was: what if the page items that are throwing drop shadows would be pretending to float at smoothly varying distances from the page - for example: page items near the middle of the page would float higher, and page items near the edges would float lower above the page.&lt;br /&gt;&lt;br /&gt;So, I set out to do some experiments using InDesign and ExtendScript, and it turns out the results are interesting - interesting enough to share as a podcast.&lt;br /&gt;&lt;br /&gt;I started with the following assumptions and limitations:&lt;br /&gt;&lt;br /&gt;All distances are expressed in points&lt;br /&gt;&lt;br /&gt;Pages and spreads have a coordinate system: an X-axis pointing to the right, a Y-axis pointing down. The origin of the coordinate system can be pretty much anywhere, but often it is somewhere in the upper left hand corner of the page or spread. In the script, I rather arbitrarily use X-Y coordinates relative to an origin that sits in the middle of each page.&lt;br /&gt;&lt;br /&gt;I introduce a third axis - a Z-axis which is assumed to point out of the page towards the viewer. A page item that floats above the page will have a positive Z-coordinate. A page item that does not float but sits on the page has a Z-coordinate equal to zero. Because pages are considered to be opaque, negative Z-coordinates don't make much sense in this model, as they would simulate page items behind the page.&lt;br /&gt;&lt;br /&gt;I assume there is a simulated light source hovering at some point above the page. The point has some X and Y coordinates (which express the point on the page above which the light source is located) and a Z coordinate (which expresses how high above the page the light source is hovering).&lt;br /&gt;&lt;br /&gt;As far as the page items go: in addition to their X- and Y-coordinate data, selected page items are assumed to also have a Z-coordinate which shows how high above the page these page items are supposed to be floating (so they can cast a shadow). &lt;br /&gt;&lt;br /&gt;I simplified things by representing each page item by a single point - the page item's center, which is easily calculated as the mean values of the bounding box X- and Y-coordinates. &lt;br /&gt;&lt;br /&gt;To get an interesting Z-coordinate I used a mathematical formula that takes these X and Y coordinates and returns a Z coordinate. &lt;br /&gt;&lt;br /&gt;One of the formulas in the example scripts gives a Z coordinate that has its highest values for page items in the middle of the page, and gets lower for page items near the borders of the page (for the mathematically inclined: an elliptic paraboloid).&lt;br /&gt;&lt;br /&gt;To calculate the parameters of the drop shadow of each individual page item, I went back to some of my high-school geometry formulas. Using the (X,Y,Z) coordinates of the light source and the (X,Y,Z) coordinates of each page item's center, I calculated the amount of X- and Y shift to apply to the drop shadows.&lt;br /&gt;&lt;br /&gt;To work the magic, I also assumed that the script would only affect page items that are located on a page layer - I called the layer "magic carpet" (all lowercase, one space). Only page items on this layer are affected by my example script.&lt;br /&gt;&lt;br /&gt;Finally, to get some visuals, I decided to first create a page filled with a regular pattern of square page items. The script will of course work with any kind and any amount of page items on the "magic carpet" layer, but I expected the best visual effect with a regular spaced grid of page items.&lt;br /&gt;&lt;br /&gt;I created a new document, created a layer "magic carpet". Then I used two step-and-repeat operations to sprinkle a host of small, colored squares all over the page (about 6 squares horizontally and 11 squares vertically, with a good gap between them). You first create a single square, and use step-and-repeat with a horizontal displacement of..., then select the row of squares, and do a second step-and-repeat with a vertical displacement of ...)&lt;br /&gt;&lt;br /&gt;The I ran my little script - and suddenly I was presented with quite a nice 3-D effect. &lt;br /&gt;&lt;br /&gt;The script and example documents I used are available for download from this blog (rorohiko.blogspot.com).&lt;br /&gt;&lt;br /&gt;Step-by-step:&lt;br /&gt;&lt;br /&gt;On InDesign CS or CS2, you install the file 'ShadowDance.js' into the Presets - Scripts subfolder of your InDesign application folder. The script uses .js as its file name extension instead of .jsx - that way the same script works on CS as well as CS2 and CS3.&lt;br /&gt;&lt;br /&gt;On InDesign CS3, you install the file 'ShadowDance.js' into one of the script folders - I installed it in Scripts - Scripts Panel.&lt;br /&gt;&lt;br /&gt;Launch InDesign and create a new document. &lt;br /&gt;&lt;br /&gt;Create a new layer called 'magic carpet'.&lt;br /&gt;&lt;br /&gt;On this layer, create a single square, about 60x60 points in size (about 20 mm x 20 mm); position it in the top left hand corner.&lt;br /&gt;&lt;br /&gt;Fill the square with a color.&lt;br /&gt;&lt;br /&gt;Use Edit - Step and Repeat... to create five or six duplicates of the square, with a horizontal offset slightly larger than the side of the square (e.g. 72 pt or 25 mm), and a vertical offset of zero.&lt;br /&gt;&lt;br /&gt;Select the whole row of squares, and create 9 or 10 duplicates of the row of squares, this time with a horizontal offset of zero and a vertical offset slightly larger than the side of the square.&lt;br /&gt;&lt;br /&gt;You should now have a page that is covered with a regular grid of square page items, all of which sit on the 'magic carpet' layer.&lt;br /&gt;&lt;br /&gt;Bring up your scripts pallette (Window - Scripting - Scripts in CS, Window - Automation - Scripts in CS2 and CS3. In CS3, look under 'Application' if you installed the script into the Scripts - Scripts Panel folder).&lt;br /&gt;&lt;br /&gt;Double-click the script 'ShadowDance.js'. You should get a result that looks similar to what you find in the example document 'ShadowDanceCS.indd'.&lt;br /&gt;&lt;br /&gt;Till next time!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1401434775260820755-1778732065555393093?l=rorohiko.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=wWAChjvF"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=52HvneCi"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=42" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=YFsJAxYk"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=VWvgT0VL"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?i=VWvgT0VL" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=oBTLbYHl"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=OezcvQLs"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?i=OezcvQLs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=R31q4ga5"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?i=R31q4ga5" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=3M61oJXJ"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=134" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rorohiko/~4/rpOeifC2NZY" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2007-08-01T21:54:24.192-07:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><media:content url="http://feedproxy.google.com/~r/Rorohiko/~5/jEMbp9RVgac/ShadowDanceExampleFiles.zip" fileSize="29939" type="application/zip" /><itunes:explicit>no</itunes:explicit><itunes:subtitle>Example Files: Click here to download sample script and sample document Example result: Rough Transcript of Podcast: Hi, my name is Kris Coppieters from Rorohiko, and this is my second 'Lighting Brain' podcast - about having fun with drop shadows in InDes</itunes:subtitle><itunes:author>Kris Coppieters</itunes:author><itunes:summary>Example Files: Click here to download sample script and sample document Example result: Rough Transcript of Podcast: Hi, my name is Kris Coppieters from Rorohiko, and this is my second 'Lighting Brain' podcast - about having fun with drop shadows in InDesign. Initially, I'll try to create a number of podcasts in fairly quick succession, as to build up some content on the Rorohiko blog, but in the long run I aim to release a new podcast about once every two weeks. This episode I wanted to talk a bit about some fun experiments I did with drop shadows in InDesign. My brain seems to be a magnet for ideas - which would be fine, if only all ideas that pop up would be useful. Sadly enough, some of my ideas are rather silly, and this podcast is based on one of the silly ones. The podcast will also delve a little bit into some mathematical aspects of my experiments. However, even if you are not mathematically inclined you should still be able to have fun with the example document and example script - so even if the mathematics gives you the blue shivers, don't worry! Just download the sample files and have fun! My idea was this: assume there are a number of page items scattered over a page or spread. Why not coordinate all these drop shadows so they cause some visual effect to occur? Standard drop shadows are rather dull. They simulate what would happen if there was a light source at infinite distance throwing light on a page item floating at a particular height above the page. What I was wondering about was: what would happen if the simulated light source was not at infinite distance, but instead somewhere else - for example, located on the viewer's head, close to the paper, like a head-torch, or if the light source was simulating one of those swiveling desk lights. The other thing I wondered about was: what if the page items that are throwing drop shadows would be pretending to float at smoothly varying distances from the page - for example: page items near the middle of the page would float higher, and page items near the edges would float lower above the page. So, I set out to do some experiments using InDesign and ExtendScript, and it turns out the results are interesting - interesting enough to share as a podcast. I started with the following assumptions and limitations: All distances are expressed in points Pages and spreads have a coordinate system: an X-axis pointing to the right, a Y-axis pointing down. The origin of the coordinate system can be pretty much anywhere, but often it is somewhere in the upper left hand corner of the page or spread. In the script, I rather arbitrarily use X-Y coordinates relative to an origin that sits in the middle of each page. I introduce a third axis - a Z-axis which is assumed to point out of the page towards the viewer. A page item that floats above the page will have a positive Z-coordinate. A page item that does not float but sits on the page has a Z-coordinate equal to zero. Because pages are considered to be opaque, negative Z-coordinates don't make much sense in this model, as they would simulate page items behind the page. I assume there is a simulated light source hovering at some point above the page. The point has some X and Y coordinates (which express the point on the page above which the light source is located) and a Z coordinate (which expresses how high above the page the light source is hovering). As far as the page items go: in addition to their X- and Y-coordinate data, selected page items are assumed to also have a Z-coordinate which shows how high above the page these page items are supposed to be floating (so they can cast a shadow). I simplified things by representing each page item by a single point - the page item's center, which is easily calculated as the mean values of the bounding box X- and Y-coordinates. To get an interesting Z-coordinate I used a mathematical formula that takes these X and Y coordinates and returns a Z coordinate. One of the formulas in the exa</itunes:summary><itunes:keywords>printing,prepress,automation,InDesign,Adobe,CS,CS2,CS3,Rorohiko,plug,in,plugin,software,consultancy,design,desktop,publishing,PDF,Acrobat,XPress,QuarkXPress,XTension</itunes:keywords><feedburner:origLink>http://rorohiko.blogspot.com/2007/08/click-here-to-listen-to-fun-with-drop.html</feedburner:origLink><enclosure url="http://feedproxy.google.com/~r/Rorohiko/~5/jEMbp9RVgac/ShadowDanceExampleFiles.zip" length="29939" type="application/zip" /><feedburner:origEnclosureLink>http://www.rorohiko.com/podcast/ShadowDanceExampleFiles.zip</feedburner:origEnclosureLink></item><item><title>Lightning Brain Podcast: Click here to listen to "Getting Started with the Adobe InDesign SDK"</title><link>http://feedproxy.google.com/~r/Rorohiko/~3/pwUmFY9KCKg/getting-started-with-adobe-indesign-sdk.html</link><author>kris@rorohiko.com (Kris Coppieters)</author><pubDate>Sat, 02 May 2009 22:32:09 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-1401434775260820755.post-4246217877621261910</guid><description>Opinions, ideas and other musings about software development for printing and prepress...&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Recommended book list:&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;| Added remark, 15-Jul-2008: I have since written my own book &lt;br /&gt;| about getting started:&lt;br /&gt;|&lt;br /&gt;| &lt;a href="http://www.lulu.com/content/6890858"&gt;http://www.lulu.com/content/6890858&lt;/a&gt;&lt;br /&gt;|&lt;br /&gt;&lt;br /&gt;Effective C++ &lt;br /&gt;by Scott Myers &lt;br /&gt;Addison-Wesley &lt;br /&gt;ISBN 0-201-92488-9 &lt;br /&gt;&lt;br /&gt;More Effective C++ &lt;br /&gt;by Scott Myers &lt;br /&gt;Addison-Wesley &lt;br /&gt;ISBN 0-201-63371-X &lt;br /&gt;&lt;br /&gt;STL Tutorial and Reference Guide &lt;br /&gt;by Musser, Derge &amp; Saini &lt;br /&gt;Addison-Wesley &lt;br /&gt;ISBN 0-201-37923-6 &lt;br /&gt;&lt;br /&gt;Effective STL &lt;br /&gt;by Scott Myers &lt;br /&gt;Addison-Wesley &lt;br /&gt;ISBN 0-201-74962-9 &lt;br /&gt;&lt;br /&gt;Design Patterns – Elements of Reusable Object-Oriented Software &lt;br /&gt;by Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides &lt;br /&gt;Addison-Wesley &lt;br /&gt;ISBN 0-201-63361-2 &lt;br /&gt;&lt;br /&gt;The C++ Programming Language (Special 3rd Edition) &lt;br /&gt;by Bjarne Stroustrup  &lt;br /&gt;Addison-Wesley &lt;br /&gt;ISBN 0-201-70073-5&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Links:&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Boost:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.boost.org"&gt;http://www.boost.org&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Adobe InDesign Developer Centre:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.adobe.com/devnet/indesign/sdk/"&gt;http://www.adobe.com/devnet/indesign/sdk/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Rough podcast transcript:&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;InDesign can be approached in two ways - either you can use a high-level approach, using one of supported script languages, or you can use a low-level approach, using C++. &lt;br /&gt;&lt;br /&gt;The high-level approach is often sufficient for automating various repetitive tasks; we'll discuss this high-level approach in more detail in some future podcasts. At Rorohiko, for our own sofware development, we always try to achieve as much as possible using scripting, because development-wise scripting is so much more cost-efficient when compared to using the low-level approach and the SDK.&lt;br /&gt;&lt;br /&gt;The low-level approach becomes necessary when it comes to really tight integration, for example, getting invoived in the various drawing processes, or providing new user-interface elements. Then there is no other alternative but to use the InDesign SDK and C++ to achieve the desired results.&lt;br /&gt;&lt;br /&gt;The main aim of this particular podcast is to offer some insights into the low-level approach using C++.&lt;br /&gt;&lt;br /&gt;If you are a software developer, you might already have experience with a number of environments and languages - QuarkXPress XTension development, C, C++, Java, JavaScript,... and expect to ease into InDesign development with roughly the same amount of effort as you have needed when you started using these other environments and languages.&lt;br /&gt;&lt;br /&gt;The InDesign SDK is probably very different to anything you've ever handled before. &lt;br /&gt;&lt;br /&gt;The actual InDesign SDK is not very difficult. Granted, it is very extensive, but the concepts behind it are not much different from those in other, similar SDKs.&lt;br /&gt;&lt;br /&gt;The main difference is that the InDesign SDK is built on top of a fair number of other methodologies and concept, all fairly recent developments. If you try to step into the InDesign SDK without being well versed in most of these underlying foundations, nothing much will make sense. &lt;br /&gt;&lt;br /&gt;A would-be InDesign SDK developer should keep in mind that there are no shortcuts: you must first cover the basics before trying to work with the InDesign SDK, at the risk of repeatedly losing a lot of head-scratch time trying to understand things that are actually quite simple.&lt;br /&gt;&lt;br /&gt;It would be like trying to build and launch a satellite without first studying mathematics and physics.&lt;br /&gt;&lt;br /&gt;So, these are the four things you need to do before you can get started: &lt;br /&gt;&lt;br /&gt;1) You MUST have a very good grasp of C++ and various techniques. This is the first and foremost requirement. My recommendation is to at least read Scott Meyer's books (Effective C++, More Effective C++) a few times, especially if you come from a C background. I am sure even experienced C++ programmers who have not yet read these books will learn some important new things.&lt;br /&gt;&lt;br /&gt;2) You must gave a grasp of C++ Standard Library, specifically the STL (Standard Template Library), and the boost C++ Libraries (Boost provides free peer-reviewed portable C++ source libraries). &lt;br /&gt;&lt;br /&gt;You don't need to become an expert on these, but you need to have a good idea about what a vector is, what an iterator is, and how you use them. You also need to get a good idea of the 'mindset' behind STL and boost, and how C++ templates are used in a clever way to generate a lot of magic.&lt;br /&gt;&lt;br /&gt;3) You must be able to read UML diagrams. UML diagrams use a number of similar, but slightly different symbols to express relationships between things. Unless you know what the symbols mean, you'll miss out on a lot of information that is packed into the UML diagrams inside the InDesign SDK documentation.&lt;br /&gt;&lt;br /&gt;4) You must have had some exposure to the idea of 'Software Patterns' - the book 'Design Patterns' by the gang of four is highly recommended. You don't need to read this book from cover to cover, but you should at least read about the most important patterns and ideas.&lt;br /&gt;&lt;br /&gt;Once these four requirements are fulfilled (good grasp of C++, grasp of STL and boost, understanding UML, grasp of common software patterns) you are ready to tackle InDesign SDK programming.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1401434775260820755-4246217877621261910?l=rorohiko.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=lpTtGQN4"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=CAiTZ246"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=42" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=LT9ftFhO"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=8dGGV8KU"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?i=8dGGV8KU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=GAJffMVr"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=3fGDFWba"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?i=3fGDFWba" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=9YPowsvm"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?i=9YPowsvm" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=28eRPttZ"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=134" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rorohiko/~4/pwUmFY9KCKg" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-02T22:32:09.887-07:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><media:content url="http://feedproxy.google.com/~r/Rorohiko/~5/ZwAjqBnn0BQ/IDSDKGettingStarted.mp3" fileSize="3092110" type="audio/mpeg" /><itunes:explicit>no</itunes:explicit><itunes:subtitle>Opinions, ideas and other musings about software development for printing and prepress... Recommended book list: | Added remark, 15-Jul-2008: I have since written my own book | about getting started: | | http://www.lulu.com/content/6890858 | Effective C++</itunes:subtitle><itunes:author>Kris Coppieters</itunes:author><itunes:summary>Opinions, ideas and other musings about software development for printing and prepress... Recommended book list: | Added remark, 15-Jul-2008: I have since written my own book | about getting started: | | http://www.lulu.com/content/6890858 | Effective C++ by Scott Myers Addison-Wesley ISBN 0-201-92488-9 More Effective C++ by Scott Myers Addison-Wesley ISBN 0-201-63371-X STL Tutorial and Reference Guide by Musser, Derge &amp; Saini Addison-Wesley ISBN 0-201-37923-6 Effective STL by Scott Myers Addison-Wesley ISBN 0-201-74962-9 Design Patterns – Elements of Reusable Object-Oriented Software by Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides Addison-Wesley ISBN 0-201-63361-2 The C++ Programming Language (Special 3rd Edition) by Bjarne Stroustrup Addison-Wesley ISBN 0-201-70073-5 Links: Boost: http://www.boost.org Adobe InDesign Developer Centre: http://www.adobe.com/devnet/indesign/sdk/ Rough podcast transcript: InDesign can be approached in two ways - either you can use a high-level approach, using one of supported script languages, or you can use a low-level approach, using C++. The high-level approach is often sufficient for automating various repetitive tasks; we'll discuss this high-level approach in more detail in some future podcasts. At Rorohiko, for our own sofware development, we always try to achieve as much as possible using scripting, because development-wise scripting is so much more cost-efficient when compared to using the low-level approach and the SDK. The low-level approach becomes necessary when it comes to really tight integration, for example, getting invoived in the various drawing processes, or providing new user-interface elements. Then there is no other alternative but to use the InDesign SDK and C++ to achieve the desired results. The main aim of this particular podcast is to offer some insights into the low-level approach using C++. If you are a software developer, you might already have experience with a number of environments and languages - QuarkXPress XTension development, C, C++, Java, JavaScript,... and expect to ease into InDesign development with roughly the same amount of effort as you have needed when you started using these other environments and languages. The InDesign SDK is probably very different to anything you've ever handled before. The actual InDesign SDK is not very difficult. Granted, it is very extensive, but the concepts behind it are not much different from those in other, similar SDKs. The main difference is that the InDesign SDK is built on top of a fair number of other methodologies and concept, all fairly recent developments. If you try to step into the InDesign SDK without being well versed in most of these underlying foundations, nothing much will make sense. A would-be InDesign SDK developer should keep in mind that there are no shortcuts: you must first cover the basics before trying to work with the InDesign SDK, at the risk of repeatedly losing a lot of head-scratch time trying to understand things that are actually quite simple. It would be like trying to build and launch a satellite without first studying mathematics and physics. So, these are the four things you need to do before you can get started: 1) You MUST have a very good grasp of C++ and various techniques. This is the first and foremost requirement. My recommendation is to at least read Scott Meyer's books (Effective C++, More Effective C++) a few times, especially if you come from a C background. I am sure even experienced C++ programmers who have not yet read these books will learn some important new things. 2) You must gave a grasp of C++ Standard Library, specifically the STL (Standard Template Library), and the boost C++ Libraries (Boost provides free peer-reviewed portable C++ source libraries). You don't need to become an expert on these, but you need to have a good idea about what a vector is, what an iterator is, and how you use them. You also need to get a good idea of the 'mindset' behind ST</itunes:summary><itunes:keywords>printing,prepress,automation,InDesign,Adobe,CS,CS2,CS3,Rorohiko,plug,in,plugin,software,consultancy,design,desktop,publishing,PDF,Acrobat,XPress,QuarkXPress,XTension</itunes:keywords><feedburner:origLink>http://rorohiko.blogspot.com/2007/07/getting-started-with-adobe-indesign-sdk.html</feedburner:origLink><enclosure url="http://feedproxy.google.com/~r/Rorohiko/~5/ZwAjqBnn0BQ/IDSDKGettingStarted.mp3" length="3092110" type="audio/mpeg" /><feedburner:origEnclosureLink>http://www.rorohiko.com/mp3/IDSDKGettingStarted.mp3</feedburner:origEnclosureLink></item><item><title>Started a blog</title><link>http://feedproxy.google.com/~r/Rorohiko/~3/Ihq9zN_216U/started-blog.html</link><author>kris@rorohiko.com (Kris Coppieters)</author><pubDate>Mon, 30 Jul 2007 13:07:54 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-1401434775260820755.post-4193496111860126804</guid><description>Everyone is blogging - so I decided to give that a go too. This is the Rorohiko blog. Expect various posts, rants, musings,... about development, printing and prepress, various programming languages, mathematics, photography,... The next few posts will just be some testing material - trying out getting a podcast going, that kind of stuff.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1401434775260820755-4193496111860126804?l=rorohiko.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=ybfWvOAz"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=uEYdRDQQ"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=42" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=AmBAu797"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=DdbkGYJa"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?i=DdbkGYJa" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=IIKbfyNk"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=Mx8LwlNX"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?i=Mx8LwlNX" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=CMz27CKS"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?i=CMz27CKS" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/Rorohiko?a=PsWjr122"&gt;&lt;img src="http://feeds.feedburner.com/~f/Rorohiko?d=134" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rorohiko/~4/Ihq9zN_216U" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2007-07-30T13:07:54.571-07:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://rorohiko.blogspot.com/2007/07/started-blog.html</feedburner:origLink></item><copyright>(c) Rorohiko Ltd.</copyright><media:credit role="author">Kris Coppieters</media:credit><media:rating>nonadult</media:rating><media:description type="plain">Automation for Printing and Prepress</media:description></channel></rss>
