Copy link to clipboard
Copied
Hi;
I just started working with Framemaker scripting this afternoon and using sample scripts here I've got the main skeleton of my program complete. I know that a similar script was posted here years ago to move markers to the start of words, but the script appears to have vanished and the one I'm working on needs to move the markers to the beginning of the paragraph that they're currently residing in (it help translation immensely).
So far my program opens a book and, one chapter at at time, finds all of the Index markers. I need to move those markers, but I don't have enough of a handle on the language yet to get it working.
The key function is here:
function moveMarker(doc, mrkType, pgf, offset)
{
if (!doc.ObjectValid() )
{
return;
}
mrker = doc.FirstMarkerInDoc;
while (mrker.ObjectValid() )
{
if (mrker.MarkerTypeId.Name == mrkType)
{
var str1 = mrker.MarkerText;
/* A quick test to confirm it's finding the Index markers */
$.writeln(str1);
cnt ++;
/*
A counter to check how many Index markers it's finding
in the whole book -- will need a counter for number in each paragraph
to use as the offset from beginning of each paragraph
*/
$.writeln(cnt);
}
mrker = mrker.NextMarkerInDoc;
}
}
My thoughts are to start each paragraph with a paragraph-counter (p-counter) set to "0"; once the script finds an Index marker, it should cut the marker, then past it to the start of the paragraph using the p-counter as the offset, then increment the p-counter (that way it should always paste the marker after the last one -- so it won't re-find the markers it's already found).
The main script currently starts with the first Index marker in a document and, when it hits the end of a document, moves to the next document in a book -- I know I'll need to have it start with the first paragraph in a chapter and track paragraphs as it goes.
Any suggestions on how best to do the cut--and-paste, as well last track the paragraph the marker is in?
Any help would be greatly appreciated.
Thanks,
Walt Sterdan
This is how I would do it for the paragraph containing the insertion point. Of course, you will need a loop for all of the paragraphs in the document and then a way to process all of the files in the book, but one step at a time.
...#target framemaker
var doc = app.ActiveDoc;
// Get the paragraph containing the insertion point.
var pgf = doc.TextSelection.beg.obj;
var marker;
// Get a list of markers from the paragraph.
var textList = pgf.GetText (Constants.FTI_MarkerAnchor);
// Process the list backwards
Copy link to clipboard
Copied
Hi;
It dawns on me that finding the "next" Index marker isn't going to find the next Index marker in the book by position, but by the order of creation.
This simplifies things a bit; it means that a counter isn't needed for the offset -- I only need to cut the Index Marker and paste it at the beginning of the paragraph with offset = "0".
At this point, I only need hints as to how to cut the Index Marker that's been found, and paste it at the beginning of the "current' paragraph.
-- Walt Sterdan
Copy link to clipboard
Copied
This is how I would do it for the paragraph containing the insertion point. Of course, you will need a loop for all of the paragraphs in the document and then a way to process all of the files in the book, but one step at a time.
#target framemaker
var doc = app.ActiveDoc;
// Get the paragraph containing the insertion point.
var pgf = doc.TextSelection.beg.obj;
var marker;
// Get a list of markers from the paragraph.
var textList = pgf.GetText (Constants.FTI_MarkerAnchor);
// Process the list backwards so that the markers stay in the same order.
for (var i = textList.length - 1; i >= 0; i -= 1) {
marker = textList.obj;
if (marker.MarkerTypeId.Name === "Index") {
moveMarker (marker, pgf, doc);
}
}
function moveMarker (marker, pgf, doc) {
var textRange;
// Select the marker.
textRange = new TextRange (new TextLoc (pgf, marker.TextLoc.offset),
new TextLoc (pgf, marker.TextLoc.offset + 1));
doc.TextSelection = textRange;
// Cut the marker.
PushClipboard ();
doc.Cut ();
// Put the cursor at the beginning of the paragraph.
textRange = new TextRange (new TextLoc (pgf, 0), new TextLoc (pgf, 0));
doc.TextSelection = textRange;
// Paste the marker.
doc.Paste ();
PopClipboard ();
}
Copy link to clipboard
Copied
Hi;
Thanks very much for the quick response, it looks like it should do the job.
I'll let you know how well it works once I've had a chance to test it, but at the very least the code involving the clipboard cut/paste looks like exactly what was stumping me.
Thanks again,
Walt
Copy link to clipboard
Copied
I (ham-handedly) cobbled your copy/paste text with another program that traverses the book and wound up with a program that finds all of the Index markers, but doesn't move them and instead garbles the first paragraph of the first chapter containing index markers horribly.
traverseBook();
function traverseBook()
{
var book = app.ActiveBook;
if (!book.ObjectValid() )
{
return;
}
var mrkType = "Index";
var comp=book.FirstComponentInBook;
while(comp.ObjectValid())
{
doc = open(comp.Name);
if (doc.ObjectValid() )
{
moveMarker(doc, mrkType);
doc.SimpleSave(doc.Name,false);
doc.Close(Constants.FF_CLOSE_MODIFIED)
}
comp = comp.NextBookComponentInDFSOrder;
}
}
function moveMarker (doc, mrkType)
{
var textRange;
if (!doc.ObjectValid() )
{
return;
}
mrker = doc.FirstMarkerInDoc;
while (mrker.ObjectValid() )
{
// Only do with Inde Markers
if (mrker.MarkerTypeId.Name == mrkType)
{
// set pgf to current insertion point
var pgf = doc.TextSelection.beg.obj;
// Write the text of the Index marker to the console to confirm find
var str1 = mrker.MarkerText;
$.writeln (str1);
// at this point we've confirmed that the current marker is an Index marker
textRange = new TextRange (new TextLoc (pgf, mrker.TextLoc.offset),
new TextLoc (pgf, mrker.TextLoc.offset + 1));
doc.TextSelection = textRange;
// Cut the marker.
PushClipboard ();
doc.Cut ();
// Put the cursor at the beginning of the paragraph.
textRange = new TextRange (new TextLoc (pgf, 0), new TextLoc (pgf, 0));
doc.TextSelection = textRange;
// Paste the marker.
doc.Paste ();
PopClipboard ();
}
mrker = mrker.NextMarkerInDoc;
}
}
function open(filename)
{
openProp = GetOpenDefaultParams();
i=GetPropIndex(openProp,Constants.FS_FileIsOldVersion);
openProp.propVal.ival=Constants.FV_DoOK;
i=GetPropIndex(openProp,Constants.FS_FontNotFoundInCatalog);
openProp.propVal.ival=Constants.FV_DoOK;
i=GetPropIndex(openProp,Constants.FS_FontNotFoundInDoc);
openProp.propVal.ival=Constants.FV_DoOK;
i=GetPropIndex(openProp,Constants.FS_FileIsInUse);
openProp.propVal.ival=Constants.FV_DoCancel;
i=GetPropIndex(openProp,Constants.FS_AlertUserAboutFailure);
openProp.propVal.ival=Constants.FV_DoCancel;
retParm = new PropVals();
docOpen=Open(filename,openProp,retParm);
return docOpen;
}
Note: The order of the markers doesn't matter, as they're assigned a number based on their order of creation -- if you start with the first and to go the next, you will eventually iterate through all of the markers; the index will be generated alphabetically and the index page ref's on their location. As long as all of the index markers of a given paragraph are piled up in the first position of their original paragraph, we're good.
Should I focus on traversing the book differently, or is there a simpler way to better identify the paragraph the marker is located in and cut/paste them to the first character in the paragraph?
Thanks,
Walt
Copy link to clipboard
Copied
Hi Walt,
while (mrker.ObjectValid() )
{
// set pgf to current insertion point
var pgf = doc.TextSelection.beg.obj;
At this point you do not have a textselection.
You can get the pgf with this:
pgf = mrker.TextLoc.obj
Copy link to clipboard
Copied
Hi Klaus;
Embarrassingly obvious once you point it out, but that worked perfectly!
Thanks very much for your help!
-- Wlat