Copy link to clipboard
Copied
Dear friends,
While it is quite simple to find the next marker with oDoc.NextMarkerInDoc the sequence of the found markers is not that what the user sees in the document: you get the markers in the sequence they were inserted into the document (which may be quite random). To get the same sequence as using the Find dialogue, I need ...
But again my knowledge is to low - see lines 91 or 92:
#target framemaker
/* Navigate markers and get them
Document in charge is E:\_DDDprojects\FM-calc\FM-testfiles\NavigateMarkers.fm
Which contains both #calc and Author markersIt turns out that the sequence of marker.NextMarkerInDoc is that of creating the markers.
For the first and last marker the simple method is OK (since absolute postions).
For next and previous the find method must be used.
*/
var oDoc = app.ActiveDoc, oCurrentMarker;
if (!oDoc.ObjectValid ()) {
alert ("There is no active document.");
} else {
oCurrentMarker = GetMarker (oDoc, "#calc", "first"); // OK
Alert ("marker found = " + oCurrentMarker.MarkerText);
oCurrentMarker = GetMarker (oDoc, "#calc", "next", oCurrentMarker); // undefined
Alert ("marker found = " + oCurrentMarker.MarkerText);
}
function GetMarker (oDoc, sMarkerName, sAdverb, oCurrentMarker) { // =============================
// sAdverb may be first, last, previous, next
// returns undefined if sMarkerName not defined in oDoc
// argument oCurrentMarker unused for "first"
// unfortunately there are no such methods as LastMarkerInDoc or PreviousMarkerInDoc
var marker, nextMarker, exit, currenMarker;
markerType = oDoc.GetNamedMarkerType (sMarkerName); // Get the specified marker type.
if (!markerType.ObjectValid ()) { return undefined;}
switch (sAdverb) {
case "first":
oCurrentMarker = GetFirstMarker (oDoc, sMarkerName);
break;
case "previous":
oCurrentMarker = FindNextPrevMarker (oDoc, sMarkerName, "previous", oCurrentMarker);
break;
case "next":
oCurrentMarker = FindNextPrevMarker (oDoc, sMarkerName, "next", oCurrentMarker);
break;
case "last":
oCurrentMarker = GetLastMarker (oDoc, sMarkerName);
break;
default:
Alert ("Error in routine NavigateMarker\nUndefined sAdverb = " + sAdverb);
break;
}
return oCurrentMarker;
}function GetFirstMarker (oDoc, sMarkerName) { // get first marker of type sMarkerName =============
// function returns the current marker, null if it does not exist
// parameter oCurrentMarker is not used
var marker = null, nextMarker, oCurrentMarker;
marker = oDoc.FirstMarkerInDoc;
while (marker.ObjectValid ()) {
nextMarker = marker.NextMarkerInDoc;
if (marker.MarkerTypeId.Name === sMarkerName) {
return marker;
}
marker = nextMarker;
}
}function GetLastMarker (oDoc, sMarkerName) { // get last marker of type sMarkerName ===============
// function returns the last marker of type sMarkerName, null if it does not exist
// parameter oCurrentMarker is not used
var marker, nextMarker, lastMarker;
marker = oDoc.FirstMarkerInDoc;
marker = marker.NextMarkerInDoc;
while (marker.ObjectValid ()) {
if (marker.MarkerTypeId.Name === sMarkerName) {
lastMarker = marker;
}
marker = marker.NextMarkerInDoc;
}
return lastMarker;
}function FindNextPrevMarker (oDoc, sMarkerName, sAdverb, oCurrentMarker) { // get next/previous ===
// function returns the current marker, null if it does not exist
// Base: Russ Ward in https://forums.adobe.com/message/3888653#3888653
var marker;
var tr = new TextRange();
var findParams = new PropVals();
tr.beg.obj = tr.end.obj = oCurrentMarker; // Starting tr is the current marker
tr.beg.offset = tr.end.offset = 0; //
// Wrapping not wanted.
findParams = GetFindParamsMarker (sMarkerName, sAdverb); // Find parameters for markerInitFA_errno (); // reset - it is write protected
//marker = oDoc.Find(tr.beg, findParams); // => undefined
marker = oDoc.Find(oCurrentMarker, findParams); // => undefined
if (FA_errno !== Constants.FE_Success) {
return undefined; // no next/previvious marker present
}
return marker; // we have found a next/prev marker
}function GetFindParamsMarker (sMarkerName, direction) { //=========================================
// Get/set the find parameters: find marker of type sMarkerName, consider direction, no wrapping around
// Returns find parameters in the functionvar findParams;
if (direction = "next") {
findParams = AllocatePropVals (1);
findParams[0].propIdent.num = Constants.FS_FindMarkerOfType;
findParams[0].propVal.valType = Constants.FT_String;
findParams[0].propVal.sval = sMarkerName;
} else { // previous
findParams = AllocatePropVals (2);
findParams[0].propIdent.num = Constants.FS_FindMarkerOfType;
findParams[0].propVal.valType = Constants.FT_String;
findParams[0].propVal.sval = sMarkerName;
findParams[1].propIdent.num = Constants.FS_FindCustomizationFlags;
findParams[1].propVal.valType = Constants.FT_Integer;
findParams[1].propVal.ival = Constants.FF_FIND_BACKWARDS;
}
return findParams;
} // --- end GetFindParamsfunction InitFA_errno() { //========================================================================
// Reset FA_errno as it is write protected. See https://forums.adobe.com/thread/962910
app.GetNamedMenu("!MakerMainMenu"); //If this fails, you've got bigger problems
return;
}
How to specify the (most likely needed) text range?
Thank You
Klaus Daube
I'm back ;-))
Just try this one.
...var oDoc = app.ActiveDoc
var oCurrentMarker;
var docStart = oDoc.MainFlowInDoc.FirstTextFrameInFlow.FirstPgf;
var MarkerList = [];
var tloc = new TextLoc (docStart, 0);
var locTextRange = new TextRange (tloc, tloc);
oDoc.TextSelection = locTextRange;
if (!oDoc.ObjectValid ()) {
alert ("There is no active document.");
}
else
{ // gather all markers-locations(objects) and store them in an array (MarkerList)
var FindParams
Copy link to clipboard
Copied
Hi Klaus,
there are some contstants that are undefined
•
Constants.FF_FIND_CONSIDER_CASE (0x01)
•
Constants.FF_FIND_WHOLE_WORD (0x02)
•
Constants.FF_FIND_USE_WILDCARDS (0x04)
•
Constants.FF_FIND_BACKWARDS (0x08)
They all return "undefined".
Maybe there are more constants undefined ( I didn't test it yet).
But in FM2015 there was an update this week and since then it works in 2015.
I didn't test it yet with FM 12/11/10.
If you are using FM12 better don't use "Constants.FF_FIND_BACKWARDS" but just type "8" (no quotes).
Copy link to clipboard
Copied
Thanks to Klaus Gobel's answer to my other post I'm very close to a solution: The script finds the next marker of defined type.
But I do not know how to get the new object - as a starting point for the next call of the function:
function FindNextPrevMarker (oDoc, oCurrentMarker) { //
// function returns the nextmarker, null if it does not exist
var tRange, fRange, marker;
var tLoc1 = oCurrentMarker.TextLoc;
var tLoc2 = tLoc1;
tLoc1.offset = tLoc1.offset+1; // Just behind the marker
tLoc2.offset = tLoc1.offset;
tRange = new TextRange(tLoc1,tLoc2); // TextRange after current markervar findParams = new PropVals(); // Get the find parameters for finding marker
findParams = AllocatePropVals (1);
findParams[0].propIdent.num = Constants.FS_FindMarkerOfType;
findParams[0].propVal.valType = Constants.FT_String;
findParams[0].propVal.sval = "#calc"; // How to find ANY marker ?
// findParams = GetFindParamsMarker (sMarkerName, sAdverb);InitFA_errno (); // reset - it is write protected
fRange = oDoc.Find(tRange.beg, findParams); // finds text range
oDoc.TextSelection = fRange; //? What is selected?
oDoc.ScrollToText(fRange); //? show it to me
marker = fRange.beg.obj; // is object Pgf!
if (FA_errno !== Constants.FE_Success) {
return undefined; // no next/previvious marker present
}
return marker; // we have found a next/prev marker
}
Stopping the script at line 22 see that the possible next marker has been selected (item after the 2 -> indicator):
But the result of my search (line 19) is a paragraph object. How do I get from this the marker object (for the next call of this function)?
Line 21 obviously is wrong.
And BTW would it be correct to start a backwards search with replacing line 06 by:
tLoc1.offset = tLoc1.offset-1; // just before the marker
and of course the extended set of the find-paramters as listed in my initial post (function GetFindParamsMarker)
And - what to put in line 14 to find any type of marker, just the next one in sequence?
Copy link to clipboard
Copied
If you have found the range, where the marker resides, you need to get the texitem(s):
var FoundMarker = [];
var MarkerRange = oDoc.GetTextForRange (locTrefferListe, Constants.FTI_MarkerAnchor);
for (var i = 0; i < MarkerRange.length; i++)//maybe you'll find more markers
{
var oTextItem = MarkerRange;
FoundMarker.push(oTextItem.obj)//gather all markers
}
You're done (with the marker).
To find any marker:
findParams[0].propIdent.num = Constants.FS_FindObject;
findParams[0].propVal.valType = Constants.FT_Integer;
findParams[0].propVal.ival = Constants.FV_FindAnyMarker;
To ease jumping backward and forward I would suggest to fill an array with the markers.
I will code it in a while, but it will take some time.
Then I'll be back (hasta la vista).
Copy link to clipboard
Copied
I'm back ;-))
Just try this one.
var oDoc = app.ActiveDoc
var oCurrentMarker;
var docStart = oDoc.MainFlowInDoc.FirstTextFrameInFlow.FirstPgf;
var MarkerList = [];
var tloc = new TextLoc (docStart, 0);
var locTextRange = new TextRange (tloc, tloc);
oDoc.TextSelection = locTextRange;
if (!oDoc.ObjectValid ()) {
alert ("There is no active document.");
}
else
{ // gather all markers-locations(objects) and store them in an array (MarkerList)
var FindParams = GetFindParams()
var foundTextRange = oDoc.Find(tloc, FindParams);
while (foundTextRange.beg.obj.ObjectValid())
{
MarkerList.push(foundTextRange);
tloc = foundTextRange.end;
foundTextRange = oDoc.Find(tloc, FindParams);
}
var FoundMarker = [];
for (var i = 0; i < MarkerList.length; i++)
{
var MarkerTI = oDoc.GetTextForRange (MarkerList, Constants.FTI_MarkerAnchor);
oDoc.TextSelection = MarkerList;
oDoc.ScrollToText (MarkerList);
alert("MARKER");
for (var x = 0; x < MarkerTI.length; x++)
{
var oTextItem = MarkerTI
; FoundMarker.push(oTextItem.obj)//store the marker objects
}
}
}
function GetFindParams()
{
var FindParams = new PropVals() ;
var propVal = new PropVal() ;
propVal.propIdent.num = Constants.FS_FindWrap ;
propVal.propVal.valType = Constants.FT_Integer;
propVal.propVal.ival = 0 ;// don't start at the beginning
FindParams.push(propVal);
propVal = new PropVal() ;
propVal.propIdent.num = Constants.FS_FindObject;
propVal.propVal.valType = Constants.FT_Integer;
propVal.propVal.ival = Constants.FV_FindAnyMarker ;
FindParams.push(propVal);
return FindParams
}
Copy link to clipboard
Copied
Thank You Klaus for your response as of Apr 21, 2016 4:02 PM with which I jumped a big step further.
As shown in my inital post (with my test script) I get the first marker with function GetFirstMarker and then go ahead with FindNextPrevMarker. It turns out that FindNextPrevMarker again takes the first marker. For unknown reasons fRange is before tRange:
When on line 20, the above shot was taken:
function FindNextPrevMarker (oDoc, sMarkerName, sAdverb, oCurrentMarker) { // get next/previous ===
// function returns the next/prev marker, null if it does not exist
var tRange, fRange, oTextItem, oMarker, aoMarkerRange, foundMarkers = [];
var tLoc1 = oCurrentMarker.TextLoc;
var tLoc2 = tLoc1;
if (sAdverb === "next") {
tLoc1.offset = tLoc1.offset+1; // Just behind the marker
} else {
tLoc1.offset = tLoc1.offset-1; // Just before the marker
}
tLoc2.offset = tLoc1.offset;
tRange = new TextRange(tLoc1,tLoc2); // TextRange after/before current marker
var findParams = new PropVals(); // Get the find parameters for finding marker
findParams = GetFindParamsMarker (sMarkerName, sAdverb);
InitFA_errno (); // reset - it is write protected
// this finds a text range (object pgf) of length 1, even if another marker precedes or succeds the #calc marker
fRange = oDoc.Find(tRange.beg, findParams); // finds text range (object pgf), lenght 1
aoMarkerRange = oDoc.GetTextForRange (fRange, Constants.FTI_MarkerAnchor); // this is an array
for (var j = 0; j < aoMarkerRange.length; j++) { //maybe you'll find more markers
var oTextItem = aoMarkerRange;
foundMarkers.push(oTextItem.obj) //gather all markers
}
oMarker = foundMarkers[0]; // always only 1 is found
if (FA_errno !== Constants.FE_Success) { // is this canged after the find?
return undefined; // no next/previvious marker present
}
return oMarker; // we have found a next/prev marker
}
I will, however, not follow this route any further because your idea to keep all markers in an array will ease many tasks. I have, for example noted, that the current method searches beyond the last relevant marker and hence 'wraps'. This is probably because each find is performed individually.
The method with all markers in an array will bypass all such problems and I will now close this thread and continue work with your last code.
Thank You very much for your efforts!