Copy link to clipboard
Copied
Dear Friends,
Again I have probably a weird idea: Add a cross reference in front of a footnote reference which points to that footnote.
See the FM document (FM15).
The cross reference text to be inserted is just an ellipsis. Then the whole construct (ellipsis + FN reference) will receive a character format to indicate the 'hotspot'.
Obviously I'm struggling with finding the stuff (nothing, cross-ref ellipsis, another crossref very far) in front of the FN reference.
The script first collects the FN refs of the document in an array, which allows me easy handling them back to front, thus not destroying locations of the FN anchors by inserting the ellipsis XRefs.
Most time the script works correctly, but in this test it fails at the FN anchor 3). It finds the ellipsis behind! It seems that the Find in line 67 does not search backwards but forwards.
Output of the script in first run:
Fn string =5)
XRef is there:false
Fn string =4)
oTL.offset=51 oTextItem.offset=281 dOffset=-230
XRef is there:false
Fn string =3)
oTL.offset=50 oTextItem.offset=51 dOffset=-1
XRef is there:true <<< why?
Fn string =2)
oTL.offset=310 oTextItem.offset=281 dOffset=29
XRef is there:false
Fn string =1)
oTL.offset=214 oTextItem.offset=310 dOffset=-96
XRef is there:false
Output of the script in the second run is absolutely weird. None of the present ellipsis XRefs is found and hence new ellipsis XRefs are inserted!
Fn string =5)
oTL.offset=284 oTextItem.offset=214 dOffset=70
XRef is there:false
Fn string =4)
oTL.offset=54 oTextItem.offset=284 dOffset=-230
XRef is there:false
Fn string =3)
oTL.offset=50 oTextItem.offset=54 dOffset=-4
XRef is there:false
Fn string =2)
oTL.offset=316 oTextItem.offset=50 dOffset=266
XRef is there:false
Fn string =1)
oTL.offset=217 oTextItem.offset=316 dOffset=-99
XRef is there:false
The script is not that long - but obviously I make a bad mistake somewhere - with the evaluation of the text locations. Can anyone spot this ? You must know that we currently have some heat here in Switzerland - so my brain may be somewhat out of order.
// HandleFootnote.jsx
#target framemaker
main ();
function main () {
var nNotes, oDoc;
oDoc = app.ActiveDoc;
nNotes = EnhanceInDoc (oDoc);
alert ("Number of footnotes handled: " + nNotes);
}
function EnhanceInDoc (oDoc) { //=== enhance footnotes in current document ===================
// Arguments oDoc Current document
// Returns Number of Footnote refs which got an XRef to the footnote
var bOK, aFnList = [], docStart, foundTR, j, k, lFnRef, lenFnList, nNotes=0,
sXRefFmt = "zfnref-footnote-reference", oEFN, oFindParams, oLocation, oFnTI,
oLocation, oObject, oPage, oTextItem, oTL, oTL1, oTL2, oTR, tloc;
aFnList.length = 0; // clear array
docStart = oDoc.MainFlowInDoc.FirstTextFrameInFlow.FirstPgf;
tloc = new TextLoc (docStart, 0);
oDoc.TextSelection = new TextRange (tloc, tloc); // essential
oFindParams= GetFindParameters (7, ""); // Find footnote anchor
foundTR = oDoc.Find(tloc, oFindParams);
while (foundTR.beg.obj.ObjectValid()) {
aFnList.push(foundTR); // fill array for next 'step'
tloc = foundTR.end;
foundTR = oDoc.Find(tloc, oFindParams);
}
lenFnList = aFnList.length;
if (lenFnList < 1) {
return null; // common situation for new document
}
// ---------------------------------------------- Insert link to footnote -------------------------
for (j = lenFnList-1; j >=0; j--) { // handle in reverse order to keep locations
oFnTI = oDoc.GetTextForRange (aFnList
, Constants.FTI_FnAnchor); for (k = 0; k < oFnTI.length; k++) {
oTextItem = oFnTI
; oObject = oTextItem.obj; // object Fn
oTL = oObject.TextLoc; // Location of the footnote anchor (beg)
$.writeln ("Fn string =" + oObject.FnAnchorString);
bOK = CheckXRef (oDoc, oTL, sXRefFmt);
$.writeln ("\tXRef is there:" + bOK);
if (bOK) {
break; // already an XRef inserted
} else {
lFnRef = oObject.FnAnchorString.length;
InsertXRef (oDoc, oTL, sXRefFmt, oObject, lFnRef);
nNotes += 1; // statistics, quick answer
}
}
}
return nNotes;
} //--- end EnhanceInDoc
function CheckXRef (oDoc, oTL, sXRefFmt) { //=== Test XRef at location before FN reference? ===
// Arguments oDoc: Document receiving the XRef and containing the target marker
// oTL: Text location where the XRef is assumed
// sXrefFmt: Cross reference format name assumed
// Returns true if an XRef exists inserted by InsertXRef.
// false if no XRef present or not of this kind.
// Called by EnhanceInDoc
var dOffset, foundTR, k, oFindParams, oObject, oTextItem, oXRefTI;
oFindParams= GetFindParameters (8, ""); // find XRef backwards
InitFA_errno (); // reset - it is write protected
foundTR = oDoc.Find(oTL, oFindParams);
if(FA_errno === Constants.FE_Success) { // there may be nothing in front of FN-ref
oXRefTI = oDoc.GetTextForRange (foundTR, Constants.FTI_XRefBegin);
for (k = 0; k < oXRefTI.length; k++) {
oTextItem = oXRefTI
; oObject = oTextItem.obj; // object XRef ?
dOffset = oTL.offset - oTextItem.offset; // Crucial part not yet working correctly
$.writeln("\toTL.offset="+oTL.offset +" oTextItem.offset="+oTextItem.offset +" dOffset="+dOffset);
if (oObject.XRefFmt.Name == sXRefFmt) { // this may be be a wrapped around XRef!
if (dOffset <= 3 && dOffset >= -1) { return true;} // inserted item is close
}
}
}
return false;
} //--- end CheckXRef
function InsertXRef (oDoc, oTL, sXRefFmt, oTgtObj, lFnRef) { //=== Insert XRef at location ============
// Arguments oDoc: Document receiving the XRef and containing the target marker
// oTL: Text location Where to insert the XRef. May be empty, defining only an Insertion Point
// sXrefFmt: Cross reference format name from the catalogue
// oTgtObj: To where the XRef shall point
// lFnRef: Length of the FN reference string
// Returns -
// Called by EnhanceInDoc
// Comment This script handles only reference and target in the same document
// Reference https://forums.adobe.com/thread/2088696
var oEFN, oHTR, oMarker, oXRef, sXRefID, oFnPgf, oTloc;
// --- Prepare the required information ------------
sXRefID = oTgtObj.id + ":" + oTgtObj.Unique; // take properties from the oTgtObj
oFnPgf = oTgtObj.FirstPgf;
oTloc = new TextLoc (oFnPgf, 0);
// --- Create the Cross reference Marker -----------
oMarker = oDoc.NewAnchoredMarker(oTloc); // Marker to be inserted in target object
oMarker.MarkerTypeId = oDoc.GetNamedMarkerType ("Cross-Ref"); //Make it a Cross-Ref marker
oMarker.MarkerText = sXRefID; // Marker text needs to be unique
// --- Create the Cross reference ------------------
oXRef = oDoc.NewAnchoredFormattedXRef(sXRefFmt, oTL); // Insert a new xref object
oXRef.XRefSrcIsElem = false; // Required to make it an unstructured xref
oXRef.XRefFile = oDoc.Name; // Required for same file ?
oXRef.XRefSrcText = oMarker.MarkerText;
oDoc.UpdateXRef(oDoc, oXRef); //Update the new xref.
// --- Apply character format to whole construct ---
oEFN = oXRef.TextRange.end; // end of XRef
oEFN.offset = oEFN.offset + lFnRef; // after FN ref string
oHTR = new TextRange (oXRef.TextRange.beg, oEFN);
applyCharFmt (oHTR, "hypertext", oDoc) ;
} //--- end InsertXRef
function GetFindParameters (iType, sSearch) { //=== set up parameters for various find actions ====
// Arguments iType: what find to be performed
// 7 Footnote (anchor)
// 8 Cross reference, backwards
// sSearch: what to search for (other types)
// Returns Parameters for the find method
var findParams, propVal;
findParams = new PropVals() ;
switch (iType) {
case 7: // ---------------------------------- find any Footnoe
propVal = new PropVal() ;
propVal.propIdent.num = Constants.FS_FindWrap ;
propVal.propVal.valType = Constants.FT_Integer;
propVal.propVal.ival = 0 ; // don't wrap
findParams.push(propVal);
propVal = new PropVal() ;
propVal.propIdent.num = Constants.FS_FindObject;
propVal.propVal.valType = Constants.FT_Integer;
propVal.propVal.ival = Constants.FV_FindFootnote ;
findParams.push(propVal);
return findParams;
case 8: // ---------------------------------- find any cross reference backwards
propVal = new PropVal() ;
propVal.propIdent.num = Constants.FS_FindWrap ;
propVal.propVal.valType = Constants.FT_Integer;
propVal.propVal.ival = 0 ; // don't wrap
findParams.push(propVal);
propVal = new PropVal() ;
propVal.propIdent.num = Constants.FS_FindCustomizationFlags ;
propVal.propVal.valType = Constants.FT_Integer;
propVal.propVal.ival = Constants.FF_FIND_BACKWARDS ;
findParams.push(propVal);
propVal = new PropVal() ;
propVal.propIdent.num = Constants.FS_FindObject;
propVal.propVal.valType = Constants.FT_Integer;
propVal.propVal.ival = Constants.FV_FindAnyXRef ;
findParams.push(propVal);
return findParams;
default:
alert ("GetFindParameters: Case " + iType + " is not defined");
return null;
}
} //--- end GetFindParameters
function applyCharFmt (textRange, name, doc) { //=== Apply character format ========================
var charFmt = 0;
charFmt = doc.GetNamedCharFmt (name);
if (charFmt.ObjectValid()) {
doc.SetTextProps (textRange, charFmt.GetProps());
}
} //--- end applyCharFmt
Markus, thanks for Your ideas - but...
Out of curiosity I wanted to see what is selected when the Find backward was performed and inserted
oDoc.TextSelection = new TextRange (oTL, oTL); // essentia
after line 41.
Then I observed that dOffset never became -1 and I eliminated the before mentioned insertion after line 75...
IMHO this is strange - but it seems to solve my problem.
Copy link to clipboard
Copied
To go further with my project I decided to insert after line 75:
if (dOffset == -1) { return false;} // The strange case
Obviously I need many more tests here, but for the time beeing brute force is applied.
I will come back and report - if I found I a better solution (based on the additional tests).
Copy link to clipboard
Copied
Hi Klaus,
I don't understand what you are doing here in detail (too hot here and too complex use gase 🙂 ).
But do you think it's a good id to use FM's find function to find previous object.
Isn't there a Chance to link These objects more intelligent, like
1. Maybe you can use UserString property (careful others can use them, too)
2. add an id to crossref (ie. UserString = crossref_4711)
3. add an id to corresponding graphic object (ie. UserString = Ellipse_4711)
So have a a link between both (or more) objects.
Maybe you can also use graphic grouping, to Keep objects together, which belongs together.
I do not know how far I shot past, Maybe I misunderstood everthing 😉
Markus
Copy link to clipboard
Copied
Markus, thanks for Your ideas - but...
Out of curiosity I wanted to see what is selected when the Find backward was performed and inserted
oDoc.TextSelection = new TextRange (oTL, oTL); // essentia
after line 41.
Then I observed that dOffset never became -1 and I eliminated the before mentioned insertion after line 75...
IMHO this is strange - but it seems to solve my problem.