Showing posts with label Text. Show all posts
Showing posts with label Text. Show all posts

2009-07-23

Get MediaSpan Jazbox Text Elements

Part of Something Bigger

If you are a MediaSpan Jazbox site there are many useful things that you can do with ExtendScript (JavaScript) to interact with your stories and pages in Adobe InCopy and Adobe InDesign documents. But some things are more difficult than others. In the case of an Adobe InCopy story from Jazbox, locating the individual InCopy stories that make up the individual Jazbox Text elements is tricky. Many things affect the ordering of those elements and you simply cannot count of app.documents[0].stories[1] being something like the head element all the time. It won't be. And once a story has hit the Adobe InDesign page the number of stories in the Adobe InCopy file can balloon. You could find that your head is suddenly stories[17].

But there is hope. There is a 'storyTitle' property in every story. But this is another one of those weird cases where a 'Story' to a user isn't the same as a 'story' to ExtendScript. Every Jazbox Text Element used in an InCopy story will have a 'storyTitle' that matches the name of the Text Element in the database. Stories that are not part of the open document won't display their 'storyTitle' property, because they are a different 'Story' placed on the page. Thus there is a method to find all the Text Elements -- find all the stories with a 'storyTitle' property.

The function below is documented to the point of showing exactly how to access any Text Element that exists in a document. You can do anything you want to them, once you know how to find them. It is another case of generating a good reference (like all the postings about generating good document references). Keep in mind that in order to allow both forms of access with the associative array that the Text Element names will be edited to not include any spaces and no other odd characters. All 'storyTitles' are run though this code:

replace (new RegExp ('[\ \'\"!?*+&-\\\/]','g'), '' ).toLowerCase()
That effectively removes spaces, single and double straight primes (quotes), exclamation marks, question marks, ampersands, both forward and back slashes, and hyphens. That was the plan at least. Looking at the regular expression, that doesn't seem quite correct. Hmm.

Perhaps the most interesting facet of the function is the way it uses an 'Associative Array'. This is really an object that you can reference in any number of ways. Try this code:
var o = new Object () ;
o['PropertyName'] = 'Hello World'
$.writeln ( o.PropertyName )

var someName = 'PropertyName'
o.PropertyName = 'Something Else'
$.writeln ( o[someName] )

$.writeln ( 'PropertyName' + ' exists: ' + o.hasOwnProperty ( 'PropertyName' ) )

$.writeln ( o.reflect.properties )
$.writeln ( o.length + ' elements is incorrect. Objects don\'t have lengths.' )

The function was created as part of a function to grab all the text elements in a particular order and recompile into another InCopy file. That had very limited use, but the function below is quite generic.

Also, Graphic Captions will also be exposed to this function, but grabbing them is a different process. I have a separate function for that. Ask and ye shall receive.

//
//-- CAUTION: WATCH OUT FOR LINE BREAKS FROM THE BLOG POSTING
//
function getJazboxStoryElements ( docRef ) {
//-------------------------------------------------------------------------
//-- Get Jazbox Story Elements
//-------------------------------------------------------------------------
//-- Generic, Yes for Jazbox
//-------------------------------------------------------------------------
//-- Purpose: To return the references to the stories in an InCopy story
//-- if the story has been placed on a page or not.
//-------------------------------------------------------------------------
//-- Returns an object containing story References
//-- The returned object will have properties with the name of each
//-- element. For example the returned object .headline, .deck,
//-- .mainmext, .nugget01, .quote
//-------------------------------------------------------------------------
//-- Basic Use:
//~ var activeStoryElements = getJazboxStoryElements(app.documents[0]);
//-------------------------------------------------------------------------
//-- Extended Use:
//-- Assume that we have activeStoryElements from the above Basic Use
//-- Now to determine if an element exists in a story. Lets assume
//-- the element name in Jazbox was 'Web Head'. The function
//-- must remove the space. And the function will also convert
//-- all the names (in the script only) to lowercase. Thus the
//-- 'Web Head' text element in Jazbox will be referred to here
//-- as 'webhead'.
//~ if ( activeStoryElements.hasOwnProperty ('webhead') ) {
//~ //-- Do something with the web head property.
//~ //-- To Grab the text:
//~ var webHeadContents = activeStoryElements['webhead'].contents
//~ //-- To Replace the contents with the 2nd paragraph of the main
//~ //-- text element as a way of populating the web head
//~ activeStoryElements['webhead'].contents =
//~ activeStoryElements.maintext.paragraphs[1].contents
//~ //-- To format the web head with a paragraph style named
//~ //-- 'Head Web Normal'
//~ activeStoryElements.webhead.appliedParagraphStyle = 'Head Web Normal'
//~ }
//-------------------------------------------------------------------------
//-- Written by Jon S. Winters of electronic publishing support
//-- jonwinters@electronicpublishingsupport.com
//-------------------------------------------------------------------------
//-- Edited: 2009.07.21 to allow space and other characters in a Text
//-- Element Name. Spaces would normally break things horrible. This
//-- version also

//-- Create the object to return.
var storyReferences = new Object () ;

//-- For the passed document reference, get a list of all the active
//-- stories and titles.
var allStories = docRef.stories ;
var allStoryTitles = docRef.stories.everyItem().storyTitle ;

//-- Loop through every story
for ( var storyIndex = allStories.length - 1 ; storyIndex >= 0 ; storyIndex-- ) {
//-- Get a variable for the active title. The Text Element will have
//-- all spaces and other undesireable characters removed and
//-- the text will be converted to lowercase. 2009.07.21
var thisTitle =
String ( allStoryTitles[storyIndex] ).replace (new RegExp ('[\ \'\"!?*+&-\\\/]','g'), '' ).toLowerCase()

//-- check to make sure there is a title. Those without titles are
//-- not part of the active Jazbox story.
if ( thisTitle != '' ) {
//-- Check the Story Title to determine which element it is.
//-- this generates a property in the object to return.
storyReferences[thisTitle] = allStories[storyIndex] ;
}
}
//-- Return the created array.
return storyReferences ;
}
//

2009-07-22

Add Note and Text to End Of Story

Part of a Story Aggregator

For a MediaSpan Jazbox site I was working at there was a need to access specific Text Elements and combine them into a specific order (look for a future post for more details). Note: If you are a Jazbox site, MediaSpan's CSS can do this same function without any user interaction. This was for a very special purpose that the site decided to script a different solution.

Back to the script... Part of adding different blobs of text together into a new Adobe InCopy story involved marking them with their original Text Element name. Notes seemed like a good choice. So this function was developed to take a reference to a story and add a note and some more text to the end of the story. It works well. While designed for Adobe InCopy this would also work for Adobe InDesign as well.


//
function addNoteAndTextToEndOfStory ( storyRef , noteString , storyString ) {
//-------------------------------------------------------------------------
//-- A D D N O T E A N D T E X T T O E N D O F S T O R Y
//-------------------------------------------------------------------------
//-- Generic: Yes for Adobe InCopy and Adobe InDesign CS3 and perhaps newer
//-------------------------------------------------------------------------
//-- Purpose: To add a note and then some text following the note at the
//-- current end of the passed Adobe InDesign or Adobe InCopy story.
//-- The original reason to do this was for a client that wanted to
//-- aggregate some paragraphs of text, but record where the text
//-- came from. So, by passing this function a reference to a story
//-- it will add a note and then the text to the end of the story.
//--
//-- Note: this function is currently set to add a blank
//-- paragraph at the end of the story each time this is to help
//-- place each subsequent addition at the beginning of a paragraph.
//-------------------------------------------------------------------------
//-- Calls: Nothing.
//-- Returns: Nothing, but modifies the story for the passed reference.
//-------------------------------------------------------------------------
//-- Sample Use:
//~ var storyRef = app.documents[0].stories[0] ;
//~ var noteContents = 'This is a note Added by A Script' ;
//~ var storyContents = 'The FirstParagraph\rThe Second\rFinal Paragraph'
//~ addNoteAndTextToEndOfStory ( storyRef , noteContents , storyContents )
//-------------------------------------------------------------------------
//-- Written: 2009.07.03 by Jon S. Winters of electronic publishing support
//-- eps@electronicpublishingsupport.com
//-------------------------------------------------------------------------
//-- To add a note to a story, we need to first add the note using the
//-- .add method. That returns a reference to the added note. The
//-- resultant note doesn't have contents, but its 'texts' does.
var noteRef = storyRef.insertionPoints[-1].notes.add() ;
noteRef.texts[0].contents = noteString ;

//-- Now insert the contents at the end of the story and add a return.
storyRef.insertionPoints[-1].contents = storyString + '\r' ;
}
//

2009-06-23

Story Has Notes

/*
Determine if there are notes in a story.
*/
//
#target incopy
var aStory = app.documents[0].stories[0] ;
if ( storyNotesExists ( aStory ) )
alert ('that story has notes' ) ;

//
function storyNotesExists ( storyRef ) {
//----------------------------------------------------------------------
//-- S T O R Y N O T E S E X I S T S
//----------------------------------------------------------------------
//-- Generic: Yes for Adobe InDesign or Adobe InCopy CS2, CS3, CS4
//----------------------------------------------------------------------
//-- Purpose: To return true or false after determining if notes exist
//-- within the passed story.
//-- This is useful if you are cleaning up stories and placing
//-- undesirable text within a note. If is extremely safe to assume
//-- that any story with notes has already been edited and/or cleaned.
//----------------------------------------------------------------------
//-- Arguments: 1
//-- storyRef: A reference to a story in Adobe InDesign or Adobe InCopy
//-- this might be in the form of many things including:
//-- app.documents[0].stories[0]
//-- app.selectionp[0].parentStory
//-------------------------------------------------------------------------
//-- Calls: Nothing
//-------------------------------------------------------------------------
//-- Returns: True or false.
//-------------------------------------------------------------------------
//-- Written by: Jon S. Winters on 2009.06.20
//-- Edited: 2009.06.23
//-- eps@electronicpublishingsupport.com
//-------------------------------------------------------------------------
try {
//-- See if passed story reference has a notes collection with more
//-- zero items. If so, return true. If not, return false.
return ( storyRef.notes.length > 0 ) ;
}
catch (err) {
//-- If anything caused an error, return false. This protects us when
//-- the function was called with something other than a story.
return false ;
}
}
//