2009-09-15

Ordinal Numbers

Below are two similar techniques for generating ordinal numbers such as 1st, 2nd, 3rd, from simple integers such as 1, 2, 3 respectively. I needed this for a fairly complex user interface where I wanted to setup a tool tip that said 'Select 1st choice:', 'Select 2nd choice', etc.
Below are both a method and a function. You only need one, not both. All that differs is how you call them. The documentation in both show the differences in sample uses.


Number.prototype.ordinal = function () {
//-------------------------------------------------------------------------
//-- O R D I N A L
//-------------------------------------------------------------------------
//-- Generic: Yes, for ECMAScript, ExtendScript, and JavaScript
//-------------------------------------------------------------------------
//-- Purpose: To take a number and return a string with that number
//-- converted to an ordinal number. Thus 1 becomes 1st. 2 becomes 2nd.
//-- 3 becomes 3rd. 12 becomes 12th.
//-------------------------------------------------------------------------
//-- Arguments: none, this is a method.
//-------------------------------------------------------------------------
//-- Calls: Nothing.
//-------------------------------------------------------------------------
//-- Returns: a string with an ordinal version of the number unless the
//-- original number is not deemed to be an integer.
//-------------------------------------------------------------------------
//-- Sample Uses:
//-- Number(13).ordinal() ;
//-- for ( i = 0 ; 100 >= i ; i++ ) {
//-- $.writeln( i.ordinal() );
//-- }
//-------------------------------------------------------------------------
//-- Notes: Tested for 0 through 200.
//-------------------------------------------------------------------------
//-- Modified: 2009.09.07 by Jon S. Winters of electronic publishing support
//-- original, undocumented concept un acknowledged but listed at:
//-- "http://querylog.com/q/javascript+string+ordinal"
//-- eps@electronicpublishingsupport.com
//-- For additional information on cardinal numbers, check out:
//-- http://en.wikipedia.org/wiki/Names_of_numbers_in_English#Ordinal_numbers
//-------------------------------------------------------------------------

//-- Start by varifying that the orginal is an integer
var asInt = parseInt ( this ) ;
if ( isNaN ( asInt ) ) { return this ; }
//-- Make a string version of the text to allow regular expression
//-- matching for the numbers.
var asString = this.toString();
//-- Do a series of if statements to concatinate the appropriate
//-- suffix to the number. All 1, 2, 3 except for 11, 12, 13
//-- have common suffixs. All others are th's.
//-- Check for items ending with 1 except for 11 and add st
if ( asInt == 1 || asString.match( new RegExp ( '[^1]1$' ) ) ) return asInt + 'st' ;
//-- Check for items ending with 2 except for 12 and add nd
if ( asInt == 2 || asString.match( new RegExp ( '[^1]2$' ) ) ) return asInt + 'nd' ;
//-- Check for items ending with 3 except for 13 and add rd
if ( asInt == 3 || asString.match( new RegExp ( '[^1]3$' ) ) ) return asInt + 'rd' ;
//-- All but these end with th. This includes 0.
return asInt + 'th';
}
function ordinal ( value ) {
//-------------------------------------------------------------------------
//-- O R D I N A L
//-------------------------------------------------------------------------
//-- Generic: Yes, for ECMAScript, ExtendScript, and JavaScript
//-------------------------------------------------------------------------
//-- Purpose: To take a number and return a string with that number
//-- converted to an ordinal number. Thus 1 becomes 1st. 2 becomes 2nd.
//-- 3 becomes 3rd. 12 becomes 12th.
//-------------------------------------------------------------------------
//-- Arguments: one, the numberical value. This should be an integer.
//-------------------------------------------------------------------------
//-- Calls: Nothing.
//-------------------------------------------------------------------------
//-- Returns: a string with an ordinal version of the number unless the
//-- original number is not deemed to be an integer.
//-------------------------------------------------------------------------
//-- Sample Use: ordinal(13)
//-------------------------------------------------------------------------
//-- Notes: Tested for 0 through 200.
//-------------------------------------------------------------------------
//-- Modified: 2009.09.07 by Jon S. Winters of electronic publishing support
//-- original, undocumented concept un acknowledged but listed at:
//-- "http://querylog.com/q/javascript+string+ordinal"
//-- eps@electronicpublishingsupport.com
//-- For additional information on cardinal numbers, check out:
//-- http://en.wikipedia.org/wiki/Names_of_numbers_in_English#Ordinal_numbers
//-------------------------------------------------------------------------

//-- Start by varifying that the orginal is an integer
//-- return the original value if it is not
var asInt = parseInt ( value ) ;
if ( isNaN ( asInt ) ) { return value ; }
//-- Make a string version of the text to allow regular expression
//-- matching for the numbers.
var asString = value.toString();
//-- Do a series of if statements to concatinate the appropriate
//-- suffix to the number. All 1, 2, 3 except for 11, 12, 13
//-- have common suffixs. All others are th's.
//-- Check for items ending with 1 except for 11 and add st
if ( asInt == 1 || asString.match( new RegExp ( '[^1]1$' ) ) ) return asInt + 'st' ;
//-- Check for items ending with 2 except for 12 and add nd
if ( asInt == 2 || asString.match( new RegExp ( '[^1]2$' ) ) ) return asInt + 'nd' ;
//-- Check for items ending with 3 except for 13 and add rd
if ( asInt == 3 || asString.match( new RegExp ( '[^1]3$' ) ) ) return asInt + 'rd' ;
//-- All but these end with th. This includes 0.
return asInt + 'th';
}

2009-09-14

Time Zone Converter

This is an interesting thing. I needed to convert the time in some sports agate files from EST or EDT as sent by the Associated Press to PST or PDT depending upon the time of year. That is a 3 hour shift. But in case I or someone needed to do this for another time zone I wanted an easy way to do this.
I took an odd approach with an Array Rotation Method. Take a look at both the method's and the function's documentation for details.
I've been intending to get this posted for some weeks, but have been tied up with projects. Let me know if you find it helpful.


/*
Time zone converter.
*/



Array.prototype.rotate = function ( offset ) {
//-------------------------------------------------------------------------
//-- R O T A T E
//-------------------------------------------------------------------------
//-- Generic: Very. Should work within any ECMA based language that
//-- supports .push(), .pop(), .shift(), and .unshift()
//-------------------------------------------------------------------------
//-- Purpose: To rotate an array around such that the end is pushed to the
//-- front, or the front is pushed onto the end. See the sample use.
//-------------------------------------------------------------------------
//-- Arguments: 1) An offset number. See samples for results.
//-- when the argument is not specified, the value defaults to 1.
//-- When a non-integer value is provided, not changes are made.
//-------------------------------------------------------------------------
//-- Calls: Nothing, but uses the 4 ExtendScript methods
//-- .push(), .pop(), .shift(), and .unshift() which exist is JavaScript
//-------------------------------------------------------------------------
//-- Returns: Nothing. Modifies the original array.
//-------------------------------------------------------------------------
//-- Sample Use: With this method declared BEFORE its use...
//~ var a = [0,1,2,3,4,5,6,7,8,9].rotate(3) ; //-- [3,4,5,6,7,8,9,0,1,2]
//~ var b = [0,1,2,3,4,5,6,7,8,9].rotate(-3) ; //-- [7,8,9,0,1,2,3,4,5,6]
//~ var c = [0,1,2,3,4,5,6,7,8,9].rotate(0) ; //-- [0,1,2,3,4,5,6,7,8,9]
//~ var d = [0,1,2,3,4,5,6,7,8,9].rotate() ; //-- [1,2,3,4,5,6,7,8,9,0]
//~ var e = [0,1,2,3,4,5,6,7,8,9].rotate('Jiggy') ; //-- [0,1,2,3,4,5,6,7,8,9]
//~ var timeDifference = - 7 ; //-- 7 hours
//~ var hourSomewhere = 14 ; //-- 2 PM (GMT?)
//~ var timeHere = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23].rotate(timeDifference)[hourSomewhere] //-- 7 AM
//-------------------------------------------------------------------------
//-- Notes: This is a mehod, not a function. It is availabe to all arrays
//-- when it is declared before its use (put it at the very top of
//-- the script file or call it with a #include).
//-------------------------------------------------------------------------
//-- Written: 2009.08.28 by Jon S. Winters of electronic publishing support
//-- eps@electronicpublishingsupport.com
//-------------------------------------------------------------------------
if ( arguments[0] == undefined ) {
offset = 1 ; //-- Default rotate up one if an arguement isn't supplied
}
//-- Make sure we can get an integer version of what was passed
offset = parseInt ( offset )

//-- Check for valid argument, if not return the original array
if ( isNaN ( offset ) || offset == 0 ) { return this ; }

//-- If the offset is negative, then rotate the end to the front
if ( 0 > offset ) {
for ( var rIndex = 0 ; rIndex > offset ; rIndex-- ) { this.unshift(this.pop()) ; }
return this ;
}
//-- implied else
//-- Rotate from the front to the end
for ( var rIndex = 0 ; offset > rIndex ; rIndex++ ) { this.push(this.shift()) ; }
return this ;
}
//




var s = 'N.Y. Mets (Redding 1-4)\
at Florida (A.Sanchez 2-4), 1:10 p.m.' ;
$.writeln ( adjustTime ( s , -3 ) )



function adjustTime ( s , offset ) {
//-------------------------------------------------------------------------
//-- A D J U S T T I M E
//-------------------------------------------------------------------------
//-- Generic: Yes, but uses the Array Method .rotate(offset).
//-- This .rotate(offset) method is provided elsewhere.
//-------------------------------------------------------------------------
//-- Purpose: To take a string, look for times and replace them with a
//-- value that is a specified number of hours different. To switch
//-- from EDT to PDT send it a -3 value.
//-------------------------------------------------------------------------
//-- Arguments: 2
//-- s: a the string to search and replact the times.
//-- offset: a number, either positive or negative to use to offset
//- the time by.
//-------------------------------------------------------------------------
//-- Calls: .rotate()
//-------------------------------------------------------------------------
//-- Returns: The string with the time swapped, or the original string
//-- if no times were found.
//-------------------------------------------------------------------------
//-- Written: 2009.08.28 by Jon S. Winters of electronic publishing support
//-- Edited Comments: 2009.10.27
//-- eps@electronicpublishingsupport.com
//-------------------------------------------------------------------------
//-- Build, as string, not Regular Expressions
//-- the 4 different patterns we need to match.
var hrPatt = '(0?[1-9]|1[012])' ;
var minPatt = '([0-5]\\d)' ;
var AMPMpatt = '\\s+[AP]\\.?M\\.?' ;
var PMpatt = '\\s+P\\.?M\\.?'

//-- Now define the main pattern and grap the matches
var matches = s.match ( new RegExp ('(' + hrPatt + ':' + minPatt + ')' + AMPMpatt ,'gim') )
//-- Check for matches, and if there are,
//-- then process each of them within a loop
if ( matches != null ) {
for ( var mIndex = matches.length - 1 ; mIndex >= 0 ; mIndex-- ) {

var allHours = [12,1,2,3,4,5,6,7,8,9,10,11,12,1,2,3,4,5,6,7,8,9,10,11]
var allAMPM = ['a.m.','a.m.','a.m.','a.m.','a.m.','a.m.','a.m.','a.m.','a.m.','a.m.','a.m.','a.m.','p.m.','p.m.','p.m.','p.m.','p.m.','p.m.','p.m.','p.m.','p.m.','p.m.','p.m.','p.m.']
//-- get the current original string
var currentMatchString = matches[mIndex] ;
//-- Now get the specifics
//-- Get the hour as a number, the minutes as a string and the AM/PM as boolean
var originalHour = parseInt ( currentMatchString.match(new RegExp ( hrPatt + ':' , 'gi' ) )[0] ) ;
var originalMinutes = currentMatchString.match (new RegExp (':' + minPatt , 'gi' ) )[0] ;
var isPM = new RegExp ( PMpatt , 'gi' ).test ( currentMatchString ) ;
//-- Figure out where the original position of that hour in the arrays
var originalIndex = originalHour ;
if ( originalHour == 12 ) { originalIndex = 0 ; }
if ( isPM ) { originalIndex = originalIndex + 12 ; }

//-- Use the array method .rotate() to find the new values at that
//-- original Index location.
var newHour = allHours.rotate(offset)[originalIndex] ;
var newAMPM = allAMPM.rotate(offset)[originalIndex] ;
//--
s = s.replace ( currentMatchString , newHour + originalMinutes + ' ' + newAMPM ) ;
} //-- end of loop
return s ;
} //-- end of match
} //
//

Revised Return Document Reference

I was using this function in a script and noticed when it was passed a collections such as you get with .pages, it didn't return a document reference. This version does this. The version posted back on June 27, 2009 has been removed.

function returnDocumentReference ( anObject ) {
//-------------------------------------------------------------------------
//-- R E T U R N D O C U M E N T R E F E R E N C E
//-------------------------------------------------------------------------
//-- Generic: Yes for most versions of Adobe InCopy or Adobe InDesign.
//-------------------------------------------------------------------------
//-- Purpose: To return a document reference for the passed object.
//-------------------------------------------------------------------------
//-- Returns: A reference to the document holding the passed object
//-- providing the object is within 32 levels of the Document
//-- or returns null if the docucment cannot be found or if an
//-- error occurs.
//-------------------------------------------------------------------------
//-- Sample Use:
//-- var docRef = returnDocumentReference ( app.selection[0] )
//-------------------------------------------------------------------------
//-- Calls: Nothing.
//-------------------------------------------------------------------------
//-- This function is not recursive, but instead loops through the
//-- object's parents, grandparents, etc. until reaching something
//-- whose constructor's name includes 'Document'. What is
//-- interesting about the function is that it is generic enough
//-- that you could easily swap the word 'Document' for another
//-- type of object. However, in Adobe InDesign and Adobe InCopy
//-- not all objects below pages have constructors.
//-------------------------------------------------------------------------
//-- Written: by Jon S. Winters
//-- Unsure of original date, but edited on 2009.09.14 in New Orleans, LA
//-- eps@electronicpublishingsupport.com
//-------------------------------------------------------------------------

// Provide an excape hatch incase something goes astray
var loopLimit = 32 ;

// Create a Regular Expression pattern
// for a case insensitive word 'Document'
var docPattern = new RegExp ( 'Document' , 'i' ) ;

// Start with the object itself incase it is the document.
var possibleDocument = anObject ;

// in case something really odd is sent, wrap in error handler
try {
// Continue looping up and chacking the parents until
// a matching document is found.
while ( ( ! docPattern.test( possibleDocument.constructor.name ) ) && ( loopLimit-- > 0 ) ){
//-- 2009.09.14 Below generates false error when a collection is passed
//-- such as .pages
try {
possibleDocument = possibleDocument.parent ;
}
catch (err ) {
//-- if the error deals with a collection of objects
//-- then try to get the parent of the first item.
if ( possibleDocument.length > 1 ) {
possibleDocument = possibleDocument[0].parent ;
}
else { return null ; } ;
}
}
// Check the loop limit and either return the document or null
if ( loopLimit > 0 ) {
return possibleDocument ; }
else { return null ; }
}
catch (err) { return null ; }
}// end of function
//

2009-07-24

Get MediaSpan Jazbox Graphic Captions

Another piece of the puzzle

Earlier I posted a function to look at an Adobe InCopy story from a MediaSpan Jazbox site that had multiple Text Elements and create a special object sometimes called an associative array. The graphic captions will be part of that special object. But their 'storyTitle' is only partly predictable because the 'storyTitle's always include the name of the graphic. So while we know they start with 'Graphic' and are followed by a number and a colon, the text after the colon is unknown. But with a Regular Expression we can find those stories whose 'storyTitle' property starts properly.

The function below will give you a reference to all the stories (InCopy's definition of a story, not yours and mine) in the passed document reference which are graphic captions. From there you can use a script to format them or do other things with them.




//
function getJazboxGraphicCaptionStories ( JazboxStoryElements ) {
//-------------------------------------------------------------------------
//-- G E T J A Z B O X G R A P H I C C A P T I O N S
//-------------------------------------------------------------------------
//-- Generic. Almost. Requires an external function.
//-------------------------------------------------------------------------
//-- Purpose: To return an array with a reference to each Jazbox caption.
//-------------------------------------------------------------------------
//-- Arguments: 1
//-- JazboxStoryElements: A custom object with properties continging
//-- each element of a story. The properties are named with the
//-- 'StoryTitle' (the text in the gray bar above each element
//-- in Adobe InCopy). For Jazbox captions, these 'storyTitle's
//-- start with "Graphic", a number, and a colon followed by
//-- a space and the image "Name". The routine to create the
//-- Jazbox elements might have these storyTitles generated
//-- with or without spaces and odd characters in their names
//-- so be careful with that.
//-------------------------------------------------------------------------
//-- Returns: An array of stories that point to the Jazbox captions.
//-------------------------------------------------------------------------
//-- Calls: Nothing.
//-------------------------------------------------------------------------
//-- Sample Use: Perhaps you wanted to get a reference to every caption
//-- 'story' in the active Adobe InCopy document. This might be
//-- useful if you had a function to format all the captions, but
//-- needed a method to find and access them. This function can
//-- return an array which can be looped through to point another
//-- funciton to the each caption to format.
//--
//~ var allCaptions = getJazboxGraphicCaptionStories ( getJazboxStoryElements ( app.documents[0] ) ) ;
//~ for ( var captionIndex = 0 ; captionIndex < allCaptions.length ; captionIndex++ ) {
//~ //-- Do what you want with the catptions
//~ formatCaption ( allCaptions[captionIndex] )
//~ }
//~ function formatCaption ( aCaption ) {
//~ try {
//~ aCaption.appliedParagraphStyle = '03_CAPTION_caption'
//~ }
//~ catch (err) { /* nothing to do */ }
//~ }
//--
//-------------------------------------------------------------------------
//-- Written: 2009.07.03 by Jon S. Winters of electronic publishing support
//-- eps@electronicpublishingsupport.com
//-------------------------------------------------------------------------

//-- Add a way for the site to limit how many captions are looked at.
var maximumNumberOfRelatedItemsAtSite = 50 ;

//-- Construct a string of all the element names to be used as a test
//-- for determining if a particular caption exists.
var storyProperties = JazboxStoryElements.reflect.properties ; // This generates an array
var storyPropertyNamesString = storyProperties.join('\t') ; // This makes the string
var numProperties = storyProperties.length ; // note there will always be some, but there may not be real captions.

//-- Construct the return array
var captions = new Array () ;

//-- Loop through the available captions
for ( var captionIndex = 0 ; captionIndex < maximumNumberOfRelatedItemsAtSite ; captionIndex++ ) {
//-- Construct a Regular Expression pattern for this Jazbox caption number
//-- IMPORTANT: if check the case of the text from the routine to get the elements.
var captionPattern = new RegExp ( 'graphic' + captionIndex + ':' , 'i' ) ;
//-- See if that caption exists before trying to find a particular reference
if ( captionPattern.test ( storyPropertyNamesString ) ) {
//-- The particualr caption exists, now find a reference to it.
for ( propertyIndex = 0 ; propertyIndex < numProperties ; propertyIndex++ ) {
if ( captionPattern.test ( storyProperties[propertyIndex] ) ) {
var fullPropertyName = storyProperties[propertyIndex].name ;
captions.push( JazboxStoryElements[fullPropertyName] ) ;
}
}
}
}
//
return captions ;
}
//

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' ;
}
//