WORKING WITH INDESIGN’S PASTEBOARD

In Adobe InDesign users often take advantage of the pasteboard as a holding area for page items. Drag a page item from the page onto the pasteboard and use it used anywhere within the spread; or copy and paste it anywhere within the document. It’s quick and efficient when working hands-on. Using pasteboard items in InDesign can pose some problems to new scripters. First, InDesign considers the pasteboard to be a hidden layer. When creating scripts that may involve items on the pasteboard, option preferences can be set to include, or not include, items on hidden layers as in the following example:

   tell application "Adobe InDesign CC 2015"
      tell find change text options 
         set include hidden layers to true
      end tell
   end tell

For this reason, your script needs to make sure that the <strong>include hidden layers</strong> property for find/change is set appropriately. Set incorrectly, your script can end up changing items stored on the pasteboard.

ITEMS ON PASTEBOARD

To access items on the pasteboard, your script needs to reference the spread. For most scripts, this can be the active spread of the active window

   tell application "Adobe InDesign CC 2015"
      set spreadRef to active spread of active window
      tell spreadRef
         set pageItems to page items of spreadRef
      end tell
   end tell

The problem is that the spread acts as a kind of “meta-container”, including all objects placed within and outside of the actual page bounds. This means that the spread is the parent for page items which are not visible as well as those that are visible. The fact that page items for the spread include items inside as well as outside of the active page bounds takes a it a little doing to reference pasteboard items specifically. InDesign provides a number of options for a script. First, your script may want to check to see if there are any items on the pasteboard.

COUNT OF PASTEBOARD ITEMS

To get the number of page items on the pasteboard as opposed to those on the actual pages of the spread:

  • Get the total number of items on the spread (spreadPageItems)
  • Get the total number of page items for pages of the spread (pageItems)
  • Subtract the total number of page items (pageItems) from the total number os spread items (spreadPageItems)

This is demonstrated by the following sample script:

Count Pasteboard Items

   set pageItemCount to 0
   tell application "Adobe InDesign CC 2015"
      set spreadRef to active spread of active window
      tell spreadRef
         set spreadPageItems to page items 
         repeat with i from 1 to count of pages
            tell page i
               set pageItemCount to pageItemCount + (count of page items)
            end tell
         end repeat
         if (count of spreadPageItems) > pageItemCount then
            set pasteboardItemCount to count of spreadPageItems - pageItemCount
         end if
         activate
         display alert ("There are " & pasteboardItemCount & " page items on the pasteboard")
      end tell 
   end tell

PASTEBOARD ITEM LIST

To filter out the items on the pasteboard from the total page items (spreadPageItems), the solution comes from looking at InDesign’s object hierarchy. A page item, whether on an actual page or on the pasteboard, returns a reference to the spread as its parent. You can test this out with a document having page items on its pages as well as on the pasteboard. Copy and paste the following into AppleScript editor and view the result after running the script:

Test Parent

   set parentList to {}
       tell application "Adobe InDesign CC 2015"
	   set spreadRef to active spread of active window
	   set itemList to every page item of spreadRef
	   repeat with eachItem in itemList
		set end of parentList to class of parent of eachItem
	   end repeat
       end tell
       parentList

Now replace the word parent in line 6 above to parent page so the statement reads:

   set end of parentList to class of parent page of thisItem

Be prepared for an invalid object error to be thrown if you try to run the script.

Now surround the statement with a try/end try block:

   try
      set end of parentList to class of parent page of thisItem
   end try

When you run the script as modified, you will discover the list of parent items is now smaller, and the class of the parent page is now page. The list now includes only the class of the parent of the actual page items (its parent page). The parent page object was added to InDesign fairly recently, sometime about version CS5.5 or CS6, I believe. If using an earlier version that does not have the parent page object, you will need to use some other method. Items on the pasteboard do not have a parent page object. To filter out pasteboard items from the page item list, the following can then be used.

Get Pasteboard Items (AppleScript)

set pasteboardItems to {} t

   tell application "Adobe InDesign CC 2015"
	set spreadRef to active spread of active window
	set itemList to every page item of spreadRef
	repeat with i from 1 to length of itemList
	   set thisItem to item i of itemList
	   if parent page of thisItem is nothing then
	      set end of pasteboardItems to thisItem
	   end if
	end repeat
   end tell
   pasteboardItems

Get PasteboardItems (ExtendScript)

      var pasteboardItems = [];
      var spreadRef = app.activeWindow.activeSpread;
      var itemList =  spreadRef.pageItems.everyItem().getElements();
      var thisItem, myParent;
      for (var i = 0; i < itemList.length; i++) {
          thisItem = itemList[i];
          myParent = thisItem.parentPage;
          if (myParent == null) {
             pasteboardItems.push(thisItem);
          }
       }
      pasteboardItems;

FILTERING

You can filter the items on the pasteboard by verifying the class of the page items inside the repeat loop::

   (*For AppleScript, inside the repeat loop:*)
   if parent page of thisItem is nothing then
       if class of thisItem is text frame then
          set end of pasteboardItems to thisItem
        end if
    end if
    //For ExtendScript, inside the repeat loop:
    if (myParent == null) {
         if (thisItem.constructor = TextFrame) {
             pasteboardItems.push(thisItem);
         }
     }

Of course, if your script only needs to get specific page items on the pasteboard (such as text frames), you could limit the initial item list to the specific page item by class instead of page items.

For AppleScript:

   set itemList to text frames of spreadRef;

For ExtendScript:

   var itemList = spreadRef.textFrames.everyItem().getElements();

ONWARD AND UPWARD

Now that you have the code to get the items on the spread pasteboard, you can expand your script to do something useful:

  • remove all of the pasteboard items
  • place a given pasteboard item onto a specified page
  • place the text from a pasteboard item into the document at the active insertion point

Place text from pasteboard item

Should you want to place the text from a pasteboard item into the active insertion point, your script will need do the following:

  1. get a reference to the active insertion point
  2. allow the user to choose the appropriate pasteboard item, if more than one item
  3. set the contents of the insertion point to the contents of the chosen pasteboard item

It’s the last bullet item above that may cause problems depending on your version of InDesign: The contents of a text frame in version 2015.1 is a reference to the frame itself. Try the following with a text frame selected:

   tell application "Adobe InDesign CC 2015"
	set selList to selection
	set selItem to item 1 of selList
	set theTest to contents of selItem
   end tell
   theTest

To get the text contained by the item, you have several options:

    • get the contents of the contents of the selItem
   set theText to contents of the contents of selItem
    • get the contents of the text frame’s parent story
set theText to contents of parent story of selItem

AppleScript

   tell application "Adobe InDesign CC 2015"
	set selList to selection
	set selItem to item 1 of selList
	set theTest to contents of contents of selItem
   theTest

ExtendScript

   var selList = app.selection;
   var selItem = selList[0];
   var theText = selItem.contents;
   theText;